We want to launch a new bastion host to run ansible on. Because we're working on the transition to ansible, it seems like being able to do that without needing puppet would be nice. This gets user management, base repo setup and whatnot installed. It doesn't remove them from the existing puppet, nor does it change the way we're calling anything that currently exists. Add bridge.openstack.org to the disabled group so that we don't try to run puppet on it. Change-Id: I3165423753009c639d9d2e2ed7d9adbe70360932changes/40/587540/9
parent
50bf5e316c
commit
0bb4232586
@ -0,0 +1,353 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Launch a new OpenStack project infrastructure node.
|
||||
|
||||
# Copyright (C) 2011-2012 OpenStack 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.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import dns
|
||||
import utils
|
||||
|
||||
import openstack
|
||||
import os_client_config
|
||||
import paramiko
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(sys.argv[0])
|
||||
|
||||
try:
|
||||
# This unactionable warning does not need to be printed over and over.
|
||||
import requests.packages.urllib3
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class JobDir(object):
|
||||
def __init__(self, keep=False):
|
||||
self.keep = keep
|
||||
self.root = tempfile.mkdtemp()
|
||||
self.inventory_root = os.path.join(self.root, 'inventory')
|
||||
os.makedirs(self.inventory_root)
|
||||
self.hosts = os.path.join(self.inventory_root, 'hosts')
|
||||
self.groups = os.path.join(self.inventory_root, 'groups')
|
||||
self.key = os.path.join(self.root, 'id_rsa')
|
||||
self.ansible_log = os.path.join(self.root, 'ansible_log.txt')
|
||||
# XXX if we need more, we might like to setup an ansible.cfg
|
||||
# file and use that rather than env vars. See
|
||||
# zuul/launcher/ansiblelaunchserver.py as an example
|
||||
self.env = os.environ.copy()
|
||||
self.env['ANSIBLE_LOG_PATH'] = self.ansible_log
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, etype, value, tb):
|
||||
if not self.keep:
|
||||
shutil.rmtree(self.root)
|
||||
|
||||
|
||||
def run(cmd, **args):
|
||||
args['stdout'] = subprocess.PIPE
|
||||
args['stderr'] = subprocess.STDOUT
|
||||
print("Running: %s" % (cmd,))
|
||||
proc = subprocess.Popen(cmd, **args)
|
||||
out = ''
|
||||
for line in iter(proc.stdout.readline, b''):
|
||||
line = line.decode('utf-8')
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.flush()
|
||||
out += line
|
||||
ret = proc.wait()
|
||||
print("Return code: %s" % (ret,))
|
||||
if ret != 0:
|
||||
raise subprocess.CalledProcessError(ret, cmd, out)
|
||||
return ret
|
||||
|
||||
|
||||
def stream_syslog(ssh_client):
|
||||
try:
|
||||
ssh_client.ssh('tail -f /var/log/syslog')
|
||||
except Exception:
|
||||
print("Syslog stream terminated")
|
||||
|
||||
|
||||
def bootstrap_server(server, key, name, volume_device, keep,
|
||||
mount_path, fs_label, environment):
|
||||
|
||||
ip = server.public_v4
|
||||
ssh_kwargs = dict(pkey=key)
|
||||
|
||||
print("--- Running initial configuration on host %s ---" % ip)
|
||||
for username in ['root', 'ubuntu', 'centos', 'admin']:
|
||||
ssh_client = utils.ssh_connect(ip, username, ssh_kwargs, timeout=600)
|
||||
if ssh_client:
|
||||
break
|
||||
|
||||
if not ssh_client:
|
||||
raise Exception("Unable to log in via SSH")
|
||||
|
||||
# cloud-init puts the "please log in as user foo" message and
|
||||
# subsequent exit() in root's authorized_keys -- overwrite it with
|
||||
# a normal version to get root login working again.
|
||||
if username != 'root':
|
||||
ssh_client.ssh("sudo cp ~/.ssh/authorized_keys"
|
||||
" ~root/.ssh/authorized_keys")
|
||||
ssh_client.ssh("sudo chmod 644 ~root/.ssh/authorized_keys")
|
||||
ssh_client.ssh("sudo chown root.root ~root/.ssh/authorized_keys")
|
||||
|
||||
ssh_client = utils.ssh_connect(ip, 'root', ssh_kwargs, timeout=600)
|
||||
|
||||
# Something up with RAX images that they have the ipv6 interface in
|
||||
# /etc/network/interfaces but eth0 hasn't noticed yet; reload it
|
||||
ssh_client.ssh('(ifdown eth0 && ifup eth0) || true')
|
||||
|
||||
if server.public_v6:
|
||||
ssh_client.ssh('ping6 -c5 -Q 0x10 review.openstack.org '
|
||||
'|| ping6 -c5 -Q 0x10 wiki.openstack.org')
|
||||
|
||||
ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'make_swap.sh'),
|
||||
'make_swap.sh')
|
||||
ssh_client.ssh('bash -x make_swap.sh')
|
||||
|
||||
if volume_device:
|
||||
ssh_client.scp(os.path.join(SCRIPT_DIR, '..', 'mount_volume.sh'),
|
||||
'mount_volume.sh')
|
||||
ssh_client.ssh('bash -x mount_volume.sh %s %s %s' %
|
||||
(volume_device, mount_path, fs_label))
|
||||
|
||||
with JobDir(keep) as jobdir:
|
||||
# Update the generated-groups file globally and incorporate it
|
||||
# into our inventory
|
||||
# Remove cloud and region from the environment to work
|
||||
# around a bug in occ
|
||||
expand_env = os.environ.copy()
|
||||
for env_key in list(expand_env.keys()):
|
||||
if env_key.startswith('OS_'):
|
||||
expand_env.pop(env_key, None)
|
||||
expand_env['ANSIBLE_LOG_PATH'] = jobdir.ansible_log
|
||||
|
||||
# Write out the private SSH key we generated
|
||||
with open(jobdir.key, 'w') as key_file:
|
||||
key.write_private_key(key_file)
|
||||
os.chmod(jobdir.key, 0o600)
|
||||
|
||||
# Write out inventory
|
||||
with open(jobdir.hosts, 'w') as inventory_file:
|
||||
inventory_file.write(
|
||||
"{host} ansible_host={ip} ansible_user=root {python}".format(
|
||||
host=name, ip=server.interface_ip,
|
||||
python='ansible_python_interpreter=/usr/bin/python3'))
|
||||
|
||||
t = threading.Thread(target=stream_syslog, args=(ssh_client,))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
ansible_cmd = [
|
||||
'ansible-playbook',
|
||||
'-i', jobdir.inventory_root, '-l', name,
|
||||
'--private-key={key}'.format(key=jobdir.key),
|
||||
"--ssh-common-args='-o StrictHostKeyChecking=no'",
|
||||
'-e', 'target={name}'.format(name=name),
|
||||
]
|
||||
|
||||
# Run the remote puppet apply playbook limited to just this server
|
||||
# we just created
|
||||
for playbook in [
|
||||
'set-hostnames.yaml',
|
||||
'base.yaml',
|
||||
]:
|
||||
run(ansible_cmd + [
|
||||
os.path.join(SCRIPT_DIR, '..', 'playbooks', playbook)],
|
||||
env=jobdir.env)
|
||||
|
||||
try:
|
||||
ssh_client.ssh("reboot")
|
||||
except Exception as e:
|
||||
# Some init system kill the connection too fast after reboot.
|
||||
# Deal with it by ignoring ssh errors when rebooting.
|
||||
if e.rc == -1:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def build_server(cloud, name, image, flavor,
|
||||
volume, keep, network, boot_from_volume, config_drive,
|
||||
mount_path, fs_label, availability_zone, environment):
|
||||
key = None
|
||||
server = None
|
||||
|
||||
create_kwargs = dict(image=image, flavor=flavor, name=name,
|
||||
reuse_ips=False, wait=True,
|
||||
boot_from_volume=boot_from_volume,
|
||||
network=network,
|
||||
config_drive=config_drive)
|
||||
|
||||
if availability_zone:
|
||||
create_kwargs['availability_zone'] = availability_zone
|
||||
|
||||
if volume:
|
||||
create_kwargs['volumes'] = [volume]
|
||||
|
||||
key_name = 'launch-%i' % (time.time())
|
||||
key = paramiko.RSAKey.generate(2048)
|
||||
public_key = key.get_name() + ' ' + key.get_base64()
|
||||
cloud.create_keypair(key_name, public_key)
|
||||
create_kwargs['key_name'] = key_name
|
||||
|
||||
try:
|
||||
server = cloud.create_server(**create_kwargs)
|
||||
except Exception:
|
||||
try:
|
||||
cloud.delete_keypair(key_name)
|
||||
except Exception:
|
||||
print("Exception encountered deleting keypair:")
|
||||
traceback.print_exc()
|
||||
raise
|
||||
|
||||
try:
|
||||
cloud.delete_keypair(key_name)
|
||||
|
||||
server = cloud.get_openstack_vars(server)
|
||||
if volume:
|
||||
volume = cloud.get_volume(volume)
|
||||
volume_device = cloud.get_volume_attach_device(volume,
|
||||
server['id'])
|
||||
else:
|
||||
volume_device = None
|
||||
bootstrap_server(server, key, name, volume_device, keep,
|
||||
mount_path, fs_label, environment)
|
||||
print('UUID=%s\nIPV4=%s\nIPV6=%s\n' % (
|
||||
server.id, server.public_v4, server.public_v6))
|
||||
except Exception:
|
||||
print("****")
|
||||
print("Server %s failed to build!" % (server.id))
|
||||
try:
|
||||
if keep:
|
||||
print("Keeping as requested")
|
||||
# Write out the private SSH key we generated, as we
|
||||
# may not have got far enough for ansible to run
|
||||
with open('/tmp/%s.id_rsa' % server.id, 'w') as key_file:
|
||||
key.write_private_key(key_file)
|
||||
os.chmod(key_file.name, 0o600)
|
||||
print("Private key saved in %s" % key_file.name)
|
||||
print(
|
||||
"Run to delete -> openstack server delete %s" % \
|
||||
(server.id))
|
||||
else:
|
||||
cloud.delete_server(server.id, delete_ips=True)
|
||||
except Exception:
|
||||
print("Exception encountered deleting server:")
|
||||
traceback.print_exc()
|
||||
print("The original exception follows:")
|
||||
print("****")
|
||||
# Raise the important exception that started this
|
||||
raise
|
||||
|
||||
return server
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("name", help="server name")
|
||||
parser.add_argument("--cloud", dest="cloud", required=True,
|
||||
help="cloud name")
|
||||
parser.add_argument("--region", dest="region",
|
||||
help="cloud region")
|
||||
parser.add_argument("--flavor", dest="flavor", default='1GB',
|
||||
help="name (or substring) of flavor")
|
||||
parser.add_argument("--image", dest="image",
|
||||
default="Ubuntu 18.04 LTS (Bionic Beaver) (PVHVM)",
|
||||
help="image name")
|
||||
parser.add_argument("--environment", dest="environment",
|
||||
help="Puppet environment to use",
|
||||
default=None)
|
||||
parser.add_argument("--volume", dest="volume",
|
||||
help="UUID of volume to attach to the new server.",
|
||||
default=None)
|
||||
parser.add_argument("--mount-path", dest="mount_path",
|
||||
help="Path to mount cinder volume at.",
|
||||
default=None)
|
||||
parser.add_argument("--fs-label", dest="fs_label",
|
||||
help="FS label to use when mounting cinder volume.",
|
||||
default=None)
|
||||
parser.add_argument("--boot-from-volume", dest="boot_from_volume",
|
||||
help="Create a boot volume for the server and use it.",
|
||||
action='store_true',
|
||||
default=False)
|
||||
parser.add_argument("--keep", dest="keep",
|
||||
help="Don't clean up or delete the server on error.",
|
||||
action='store_true',
|
||||
default=False)
|
||||
parser.add_argument("--verbose", dest="verbose", default=False,
|
||||
action='store_true',
|
||||
help="Be verbose about logging cloud actions")
|
||||
parser.add_argument("--network", dest="network", default=None,
|
||||
help="network label to attach instance to")
|
||||
parser.add_argument("--config-drive", dest="config_drive",
|
||||
help="Boot with config_drive attached.",
|
||||
action='store_true',
|
||||
default=False)
|
||||
parser.add_argument("--az", dest="availability_zone", default=None,
|
||||
help="AZ to boot in.")
|
||||
options = parser.parse_args()
|
||||
|
||||
openstack.enable_logging(debug=options.verbose)
|
||||
|
||||
cloud_kwargs = {}
|
||||
if options.region:
|
||||
cloud_kwargs['region_name'] = options.region
|
||||
cloud = openstack.connect(cloud=options.cloud, **cloud_kwargs)
|
||||
|
||||
flavor = cloud.get_flavor(options.flavor)
|
||||
if flavor:
|
||||
print("Found flavor", flavor.name)
|
||||
else:
|
||||
print("Unable to find matching flavor; flavor list:")
|
||||
for i in cloud.list_flavors():
|
||||
print(i.name)
|
||||
sys.exit(1)
|
||||
|
||||
image = cloud.get_image_exclude(options.image, 'deprecated')
|
||||
if image:
|
||||
print("Found image", image.name)
|
||||
else:
|
||||
print("Unable to find matching image; image list:")
|
||||
for i in cloud.list_images():
|
||||
print(i.name)
|
||||
sys.exit(1)
|
||||
|
||||
server = build_server(cloud, options.name, image, flavor,
|
||||
options.volume, options.keep,
|
||||
options.network, options.boot_from_volume,
|
||||
options.config_drive,
|
||||
options.mount_path, options.fs_label,
|
||||
options.availability_zone,
|
||||
options.environment)
|
||||
dns.print_dns(cloud, server)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -0,0 +1,5 @@
|
||||
- hosts: "!disabled"
|
||||
roles:
|
||||
- users
|
||||
- base-repos
|
||||
- base-server
|
@ -0,0 +1 @@
|
||||
purge_apt_sources: true
|
@ -0,0 +1 @@
|
||||
APT::Acquire::Retries "20";
|
@ -0,0 +1 @@
|
||||
Acquire::Languages "none";
|
@ -0,0 +1,10 @@
|
||||
# This file is kept updated by ansible, adapted from
|
||||
# https://help.ubuntu.com/lts/serverguide/configuration.html
|
||||
|
||||
deb http://us.archive.ubuntu.com/ubuntu bionic main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu bionic-updates main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu bionic universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu bionic-updates universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu bionic-backports main restricted universe
|
||||
deb http://security.ubuntu.com/ubuntu bionic-security main restricted
|
||||
deb http://security.ubuntu.com/ubuntu bionic-security universe
|
@ -0,0 +1,13 @@
|
||||
# This file is kept updated by ansible, adapted from
|
||||
# http://ubuntuguide.org/wiki/Ubuntu_Trusty_Packages_and_Repositories
|
||||
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty-updates main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty-updates universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty multiverse
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty-updates multiverse
|
||||
deb http://us.archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse
|
||||
deb http://security.ubuntu.com/ubuntu trusty-security main restricted
|
||||
deb http://security.ubuntu.com/ubuntu trusty-security universe
|
||||
deb http://security.ubuntu.com/ubuntu trusty-security multiverse
|
@ -0,0 +1,35 @@
|
||||
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
|
||||
# newer versions of the distribution.
|
||||
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted multiverse
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted multiverse
|
||||
|
||||
## Major bug fix updates produced after the final release of the
|
||||
## distribution.
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted multiverse
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted multiverse
|
||||
|
||||
## Uncomment the following two lines to add software from the 'universe'
|
||||
## repository.
|
||||
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
|
||||
## team. Also, please note that software in universe WILL NOT receive any
|
||||
## review or updates from the Ubuntu security team.
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial universe
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial universe
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
|
||||
|
||||
## N.B. software from this repository may not have been tested as
|
||||
## extensively as that contained in the main release, although it includes
|
||||
## newer versions of some applications which may provide useful features.
|
||||
## Also, please note that software in backports WILL NOT receive any review
|
||||
## or updates from the Ubuntu security team.
|
||||
# deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
|
||||
# deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
|
||||
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted multiverse
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted multiverse
|
||||
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
|
||||
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
|
||||
# deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
|
||||
# deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
|
@ -0,0 +1,13 @@
|
||||
# This file is kept updated by ansible, adapted from
|
||||
# https://help.ubuntu.com/lts/serverguide/configuration.html
|
||||
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial-updates main restricted
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial-updates universe
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial multiverse
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial-updates multiverse
|
||||
deb http://us.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security main restricted
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security universe
|
||||
deb http://security.ubuntu.com/ubuntu xenial-security multiverse
|
@ -0,0 +1,3 @@
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: true
|
@ -0,0 +1,18 @@
|
||||
- name: Configure apt retries
|
||||
copy:
|
||||
mode: 0444
|
||||
src: 80retry
|
||||
dest: /etc/apt/apt.conf.d/80retry
|
||||
|
||||
- name: Disable apt translations
|
||||
copy:
|
||||
mode: 0444
|
||||
src: 90no-translations
|
||||
dest: /etc/apt/apt.conf.d/90no-translations
|
||||
|
||||
- name: Replace sources.list file
|
||||
when: purge_apt_sources
|
||||
copy:
|
||||
src: 'sources.list.{{ ansible_facts.lsb.codename }}.{{ ansible_facts.architecture }}'
|
||||
dest: /etc/apt/sources.list
|
||||
notify: Update apt cache
|
@ -0,0 +1,6 @@
|
||||
- name: Set up additional repos
|
||||
include_tasks: "{{ lookup('first_found', file_list) }}"
|
||||
vars:
|
||||
file_list:
|
||||
- "{{ ansible_facts.distribution }}.yaml"
|
||||
- "{{ ansible_facts.os_family }}.yaml"
|
@ -0,0 +1,12 @@
|
||||
bastion_ipv4: 23.253.245.198
|
||||
bastion_ipv6: 2001:4800:7818:101:3c21:a454:23ed:4072
|
||||
base_packages:
|
||||
- at
|
||||
- git
|
||||
- lvm2
|
||||
- parted
|
||||
- rsync
|
||||
- rsyslog
|
||||
- strace
|
||||
- tcpdump
|
||||
- wget
|
@ -0,0 +1 @@
|
||||
export HISTTIMEFORMAT="%Y-%m-%dT%T%z "
|
@ -0,0 +1,4 @@
|
||||
# Original 1024
|
||||
* soft nofile 4096
|
||||
# Original 4096
|
||||
* hard nofile 8192
|
@ -0,0 +1,69 @@
|
||||
# Default rules for rsyslog.
|
||||
#
|
||||
# For more information see rsyslog.conf(5) and /etc/rsyslog.conf
|
||||
|
||||
#
|
||||
# First some standard log files. Log by facility.
|
||||
#
|
||||
auth,authpriv.* /var/log/auth.log
|
||||
*.*;auth,authpriv.none -/var/log/syslog
|
||||
#cron.* /var/log/cron.log
|
||||
#daemon.* -/var/log/daemon.log
|
||||
kern.* -/var/log/kern.log
|
||||
#lpr.* -/var/log/lpr.log
|
||||
mail.* -/var/log/mail.log
|
||||
#user.* -/var/log/user.log
|
||||
|
||||
#
|
||||
# Logging for the mail system. Split it up so that
|
||||
# it is easy to write scripts to parse these files.
|
||||
#
|
||||
#mail.info -/var/log/mail.info
|
||||
#mail.warn -/var/log/mail.warn
|
||||
mail.err /var/log/mail.err
|
||||
|
||||
#
|
||||
# Logging for INN news system.
|
||||
#
|
||||
news.crit /var/log/news/news.crit
|
||||
news.err /var/log/news/news.err
|
||||
news.notice -/var/log/news/news.notice
|
||||
|
||||
#
|
||||
# Some "catch-all" log files.
|
||||
#
|
||||
#*.=debug;\
|
||||
# auth,authpriv.none;\
|
||||
# news.none;mail.none -/var/log/debug
|
||||
#*.=info;*.=notice;*.=warn;\
|
||||
# auth,authpriv.none;\
|
||||
# cron,daemon.none;\
|
||||
# mail,news.none -/var/log/messages
|
||||
|
||||
#
|
||||
# Emergencies are sent to everybody logged in.
|
||||
#
|
||||
*.emerg :omusrmsg:*
|
||||
|
||||
#
|
||||
# I like to have messages displayed on the console, but only on a virtual
|
||||
# console I usually leave idle.
|
||||
#
|
||||
#daemon,mail.*;\
|
||||
# news.=crit;news.=err;news.=notice;\
|
||||
# *.=debug;*.=info;\
|
||||
# *.=notice;*.=warn /dev/tty8
|
||||
|
||||
# The named pipe /dev/xconsole is for the `xconsole' utility. To use it,
|
||||
# you must invoke `xconsole' with the `-file' option:
|
||||
#
|
||||
# $ xconsole -file /dev/xconsole [...]
|
||||
#
|
||||
# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
|
||||
# busy site..
|
||||
#
|
||||
# Commenting out since we don't install xconsoles on headless servers.
|
||||
#daemon.*;mail.*;\
|
||||
# news.err;\
|
||||
# *.=debug;*.=info;\
|
||||
# *.=notice;*.=warn |/dev/xconsole
|
@ -0,0 +1,81 @@
|
||||
[commands]
|
||||
# What kind of update to use:
|
||||
# default = yum upgrade
|
||||
# security = yum --security upgrade
|
||||
# security-severity:Critical = yum --sec-severity=Critical upgrade
|
||||
# minimal = yum --bugfix update-minimal
|
||||
# minimal-security = yum --security update-minimal
|
||||
# minimal-security-severity:Critical = --sec-severity=Critical update-minimal
|
||||
update_cmd = default
|
||||
|
||||
# Whether a message should be emitted when updates are available,
|
||||
# were downloaded, or applied.
|
||||
update_messages = yes
|
||||
|
||||
# Whether updates should be downloaded when they are available.
|
||||
download_updates = yes
|
||||
|
||||
# Whether updates should be applied when they are available. Note
|
||||
# that download_updates must also be yes for the update to be applied.
|
||||
apply_updates = yes
|
||||
|
||||
# Maximum amout of time to randomly sleep, in minutes. The program
|
||||
# will sleep for a random amount of time between 0 and random_sleep
|
||||
# minutes before running. This is useful for e.g. staggering the
|
||||
# times that multiple systems will access update servers. If
|
||||
# random_sleep is 0 or negative, the program will run immediately.
|
||||
# 6*60 = 360
|
||||
random_sleep = 360
|
||||
|
||||
|
||||
[emitters]
|
||||
# Name to use for this system in messages that are emitted. If
|
||||
# system_name is None, the hostname will be used.
|
||||
system_name = None
|
||||
|
||||
# How to send messages. Valid options are stdio and email. If
|
||||
# emit_via includes stdio, messages will be sent to stdout; this is useful
|
||||
# to have cron send the messages. If emit_via includes email, this
|
||||
# program will send email itself according to the configured options.
|
||||
# If emit_via is None or left blank, no messages will be sent.
|
||||
emit_via = stdio
|
||||
|
||||
# The width, in characters, that messages that are emitted should be
|
||||
# formatted to.
|
||||
output_width = 80
|
||||
|
||||
|
||||
[email]
|
||||
# The address to send email messages from.
|
||||
# NOTE: 'localhost' will be replaced with the value of system_name.
|
||||
email_from = root@localhost
|
||||
|
||||
# List of addresses to send messages to.
|
||||
email_to = root
|
||||
|
||||
# Name of the host to connect to to send email messages.
|
||||
email_host = localhost
|
||||
|
||||
|
||||
[groups]
|
||||
# NOTE: This only works when group_command != objects, which is now the default
|
||||
# List of groups to update
|
||||
group_list = None
|
||||
|
||||
# The types of group packages to install
|
||||
group_package_types = mandatory, default
|
||||
|
||||
[base]
|
||||
# This section overrides yum.conf
|
||||
|
||||
# Use this to filter Yum core messages
|
||||
# -4: critical
|
||||
# -3: critical+errors
|
||||
# -2: critical+errors+warnings (default)
|
||||
debuglevel = -2
|
||||
|
||||
# skip_broken = True
|
||||
mdpolicy = group:main
|
||||
|
||||
# Uncomment to auto-import new gpg keys (dangerous)
|
||||
# assumeyes = True
|
@ -0,0 +1,4 @@
|
||||
- name: Restart rsyslog
|
||||
service:
|
||||
name: rsyslog
|
||||
state: restarted
|
@ -0,0 +1,20 @@
|
||||
- name: Remove packages that make no sense for servers
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
state: absent
|
||||
loop:
|
||||
- whoopsie
|
||||
- popularity-contest
|
||||
|
||||
- name: Configure file limits
|
||||
copy:
|
||||
mode: 0644
|
||||
src: debian_limits.conf
|
||||
dest: /etc/security/limits.d/60-nofile-limit.conf
|
||||
|
||||
- name: Custom rsyslog config to disable /dev/xconsole noise
|
||||
copy:
|
||||
mode: 0644
|
||||
src: rsyslog.d_50-default.conf
|
||||
dest: /etc/rsyslog.d/50-default.conf
|
||||
notify: Restart rsyslog
|
@ -0,0 +1,22 @@
|
||||
# NOTE(pabelanger): We need to ensure ntpdate service starts on boot for
|
||||
# centos-7. Currently, ntpd explicitly require ntpdate to be running before
|
||||
# the sync process can happen in ntpd. As a result, if ntpdate is not
|
||||
# running, ntpd will start but fail to sync because of DNS is not properly
|
||||
# setup.
|
||||
- name: Ensure ntpdate service is running
|
||||
service:
|
||||
name: ntpdate
|
||||
enabled: yes
|
||||
state: running
|
||||
|
||||
- name: Configure yum cron
|
||||
copy:
|
||||
mode: 0644
|
||||
src: yum/yum-cron.conf
|
||||
dest: /etc/yum/yum-cron.conf
|
||||
|
||||
- name: Ensure yum cron service is running
|
||||
service:
|
||||
name: yum-cron
|
||||
enabled: yes
|
||||
state: running
|
@ -0,0 +1,4 @@
|
||||
- name: Install HWE kernel for arm64
|
||||
apt:
|
||||
name: linux-generic-hwe-16.04
|
||||
state: present
|
@ -0,0 +1,62 @@
|
||||
- name: Install base packages
|
||||
package:
|
||||
state: present
|
||||
name: '{{ item }}'
|
||||
loop: '{{ base_packages }}'
|
||||
|
||||
- name: Include OS-specific variables
|
||||
include_vars: "{{ item }}"
|
||||
with_first_found:
|
||||
- "{{ ansible_facts.distribution }}.{{ ansible_facts.architecture }}.yaml"
|
||||
- "{{ ansible_facts.distribution }}.yaml"
|
||||
- "{{ ansible_facts.os_family }}.yaml"
|
||||
- "default.yaml"
|
||||
|
||||
- name: Install distro specific packages
|
||||
package:
|
||||
state: present
|
||||
name: '{{ item }}'
|
||||
loop: '{{ distro_packages }}'
|
||||
|
||||
- name: Increase syslog message size in order to capture python tracebacks
|
||||
copy:
|
||||
content: '$MaxMessageSize 6k'
|
||||
dest: /etc/rsyslog.d/99-maxsize.conf
|
||||
mode: 0644
|
||||
notify: Restart rsyslog
|
||||
|
||||
- name: Ensure rsyslog is running
|
||||
service:
|
||||
name: rsyslog
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Set ssh key for managment
|
||||
authorized_key:
|
||||
state: present
|
||||
user: root
|
||||
key: |
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSLlN41ftgxkNeUi/kATYPwMPjJdMaSbgokSb9PSkRPZE7GeNai60BCfhu+ky8h5eMe70Bpwb7mQ7GAtHGXPNU1SRBPhMuVN9EYrQbt5KSiwuiTXtQHsWyYrSKtB+XGbl2PhpMQ/TPVtFoL5usxu/MYaakVkCEbt5IbPYNg88/NKPixicJuhi0qsd+l1X1zoc1+Fn87PlwMoIgfLIktwaL8hw9mzqr+pPcDIjCFQQWnjqJVEObOcMstBT20XwKj/ymiH+6p123nnlIHilACJzXhmIZIZO+EGkNF7KyXpcBSfv9efPI+VCE2TOv/scJFdEHtDFkl2kdUBYPC0wQ92rp puppet-remote-2014-09-15
|
||||
key_options: |
|
||||
from="{{ bastion_ipv4 }}:{{ bastion_ipv6 }},localhost"
|
||||
|
||||
- name: Disable byobu
|
||||
file:
|
||||
path: /etc/profile.d/Z98-byobu.sh
|
||||
state: absent
|
||||
|
||||
- name: Setup RFC3339 bash history timestamps
|
||||
copy:
|
||||
mode: 0644
|
||||
src: bash-history.sh
|
||||
dest: /etc/profile.d/bash-history.sh
|
||||
|
||||
- name: Include OS-specific tasks
|
||||
include_tasks: "{{ lookup('first_found', file_list) }}"
|
||||
static: no
|
||||
vars:
|
||||
file_list:
|
||||
- "{{ ansible_facts.distribution }}.{{ ansible_facts.lsb.codename }}.{{ ansible_facts.architecture }}.yaml"
|
||||
- "{{ ansible_facts.distribution }}.{{ ansible_facts.architecture }}.yaml"
|
||||
- "{{ ansible_facts.distribution }}.yaml"
|
||||
- "{{ ansible_facts.os_family }}.yaml"
|
@ -0,0 +1,3 @@
|
||||
distro_packages:
|
||||
- dnsutils
|
||||
- iputils-ping
|
@ -0,0 +1,9 @@
|
||||
- distro_packages:
|
||||
- bind-utils
|
||||
- iputils
|
||||
# Utils in ntp-perl are included in Debian's ntp package; we
|
||||
# add it here for consistency. See also
|
||||
# https://tickets.puppetlabs.com/browse/MODULES-3660
|
||||
- ntp-perl
|
||||
- ntpdate
|
||||
- yum-cron
|
@ -0,0 +1,3 @@
|
||||
all_users: {}
|
||||
disabled_users: []
|
||||
extra_users: []
|
@ -0,0 +1,69 @@
|
||||
#
|
||||
# Please note that the parameters in this configuration file control the
|
||||
# behavior of the tools from the shadow-utils component. None of these
|
||||
# tools uses the PAM mechanism, and the utilities that use PAM (such as the
|
||||
# passwd command) should therefore be configured elsewhere. Refer to
|
||||
# /etc/pam.d/system-auth for more information.
|
||||
#
|
||||
|
||||
# *REQUIRED*
|
||||
# Directory where mailboxes reside, _or_ name of file, relative to the
|
||||
# home directory. If you _do_ define both, MAIL_DIR takes precedence.
|
||||
# QMAIL_DIR is for Qmail
|
||||
#
|
||||
#QMAIL_DIR Maildir
|
||||
MAIL_DIR /var/spool/mail
|
||||
#MAIL_FILE .mail
|
||||
|
||||
# Password aging controls:
|
||||
#
|
||||
# PASS_MAX_DAYS Maximum number of days a password may be used.
|
||||
# PASS_MIN_DAYS Minimum number of days allowed between password changes.
|
||||
# PASS_MIN_LEN Minimum acceptable password length.
|
||||
# PASS_WARN_AGE Number of days warning given before a password expires.
|
||||
#
|
||||
PASS_MAX_DAYS 99999
|
||||
PASS_MIN_DAYS 0
|
||||
PASS_MIN_LEN 5
|
||||
PASS_WARN_AGE 7
|
||||
|
||||
#
|
||||
# Min/max values for automatic uid selection in useradd
|
||||
#
|
||||
SYS_UID_MIN 201
|
||||
SYS_UID_MAX 499
|
||||
UID_MIN 3000
|
||||
UID_MAX 60000
|
||||
|
||||
#
|
||||
# Min/max values for automatic gid selection in groupadd
|
||||
#
|
||||
SYS_GID_MIN 201
|
||||
SYS_GID_MAX 499
|
||||
GID_MIN 3000
|
||||
GID_MAX 60000
|
||||
|
||||
#
|
||||
# If defined, this command is run when removing a user.
|
||||
# It should remove any at/cron/print jobs etc. owned by
|
||||
# the user to be removed (passed as the first argument).
|
||||
#
|
||||
#USERDEL_CMD /usr/sbin/userdel_local
|
||||
|
||||
#
|
||||
# If useradd should create home directories for users by default
|
||||
# On RH systems, we do. This option is overridden with the -m flag on
|
||||
# useradd command line.
|
||||
#
|
||||
CREATE_HOME yes
|
||||
|
||||
# The permission mask is initialized to this value. If not specified,
|
||||
# the permission mask will be initialized to 022.
|
||||
UMASK 077
|
||||
|
||||
# This enables userdel to remove user groups if no members exist.
|
||||
#
|
||||
USERGROUPS_ENAB yes
|
||||
|
||||
# Use SHA512 to encrypt password.
|
||||
ENCRYPT_METHOD SHA512
|
@ -0,0 +1,49 @@
|
||||
- name: Setup login.defs file
|
||||
copy:
|
||||
dest: /etc/login.defs
|
||||
src: '{{ ansible_facts.os_family }}/login.defs'
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
|
||||
- name: Delete old users
|
||||
loop: "{{ disabled_users }}"
|
||||
user:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
remove: yes
|
||||
|
||||
- name: Add groups
|
||||
loop: "{{ base_users + extra_users }}"
|
||||
group:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
gid: "{{ all_users[item].gid|default(omit) }}"
|