diff --git a/docs/_static/worker_start.sh b/docs/_static/worker_start.sh index e2b4424aed..d2488b083b 100644 --- a/docs/_static/worker_start.sh +++ b/docs/_static/worker_start.sh @@ -9,7 +9,7 @@ function start_workers_for_tube { echo "Starting $2 workers for $1" for i in `seq 1 $2` do - teuthology-worker -v --archive-dir $ARCHIVE --tube $1 --log-dir $WORKER_LOGS & + teuthology-worker -v --archive-dir $ARCHIVE --tube $1 --log-dir $WORKER_LOGS 2>>/tmp/teuthology_worker_$1_$i.error & done } diff --git a/setup.cfg b/setup.cfg index c6a5b4c892..add494d78d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -65,6 +65,7 @@ scripts = [options.entry_points] console_scripts = teuthology = scripts.run:main + teuthology-deploy = teuthology.deploy:main teuthology-openstack = scripts.openstack:main teuthology-suite = scripts.suite:main teuthology-ls = scripts.ls:main diff --git a/teuthology/deploy/__init__.py b/teuthology/deploy/__init__.py new file mode 100644 index 0000000000..a17217afb1 --- /dev/null +++ b/teuthology/deploy/__init__.py @@ -0,0 +1,677 @@ +import docopt +import json +import logging +import openstack +import os +import shutil +import sys +import time +import yaml + +from pathlib import Path + +from teuthology.orchestra.remote import Remote +from teuthology.repo_utils import fetch_repo +from teuthology.misc import sh + +default_deployment_type = 'openstack' +#default_os_image='openSUSE-Leap-15.2-JeOS.x86_64-15.2-OpenStack-Cloud-Build31.415' +default_os_image='openSUSE-Leap-15.3-JeOS.x86_64-15.3-OpenStack-Cloud-Build9.122' + +if 'opensuse' in default_os_image.lower(): + default_username = 'opensuse' +else: + default_username = 'root' + + +doc = """ +usage: teuthology-deploy --help + teuthology-deploy [-v] [options] + +Deploy teuthology to a given host. + + +Options: + + -h, --help Show this help message and exit + -v, --verbose Show more detailed info + -d, --debug Show debug info + +Command options: + --clean Cleanup deployment. + --list List available deployments. + --ssh Login to the deployment node.. + + -K, --clean-on-error Cleanup deployment if an error occurred. + -n, --name Deployment name [default: {default_name}] + -N, --name-server Setup name server and nsupdate_web. + --domain Target nodes domain name + -C, --teuthology-config Use teuthology-config on deployment node + -L, --libcloud-config Extra teuthology yaml file + --libcloud-ssl-cert Path to libcloud ssl cert file, for example: + /usr/share/pki/trust/anchors/SUSE_Trust_Root.crt.pem + --dispatcher Deploy dispatcher with given job limit. + --workers Deploy given number of workers. + --targets Add targets to the platform. + + + -u, --username Remote server login name [default: {default_username}] + -i, --identity-file Remote server access ssh secret file + [default: {default_identity_file}] + + -D, --deployment-type Use following backend: openstack, libvirt, ssh + [default: openstack] + + --ceph-cm-ansible Path to ceph-cm-ansible repo clone + [default: {ceph_cm_ansible}] +Deployment Options: + + --teuthology-repo Teuthology repo URL [default: {teuthology_repo}] + --pulpito-repo Pulpito repo URL + --paddles-repo Paddles repo URL + --ceph-repo Ceph repo URL + +OpenStack Options: + + --os-cloud Deploy teuthology to the given cloud + [default: {default_os_cloud}] + --os-image Override openstack image for deployment + [default: {default_os_image}] + --os-flavor Override openstack flavor for deployment, for example: + s1-8, b2-7 [default: b2-7] + --os-floating Use floating network for deployment + --os-network Use network for deployment node + --os-keypair Use keyname for booting node [default: {default_os_keypair}] + --os-userdata Use custom userdata for node creation + +Host Options: + + -H, --host Deployment host name or ip with ssh access. + + +Examples: + +1. Build teuthology in openstack, setup named and nsupdate_web, start 8 workers and + register 50 openstack clients in paddles. + + teuthology-deploy -N --workers 8 --targets 50 + +2. Build teuthology in openstack cloud 'de' with 'teuth-featured' name from another + teuthology fork repository. + + teuthology-deploy -N --os-cloud de --name featured --teuthology-repo https://github.com/fork/teuthology + +""".format( + default_name=os.environ.get('USER'), + default_os_cloud=os.environ.get('OS_CLOUD'), + default_os_image=default_os_image, + default_os_keypair=os.environ.get('USER'), + default_username=default_username, + default_identity_file=os.environ.get('HOME') + '/.ssh/id_rsa', + ceph_cm_ansible='git+https://github.com/ceph/ceph-cm-ansible@master', + teuthology_repo='https://github.com/ceph/teuthology', +) + + +from urllib.parse import urlparse + +class Repo: + ref = None + url = None + def __init__(self, uri: str, default_ref: str): + if uri.startswith('git+'): + _uri = uri[4:] + else: + _uri = uri + u = urlparse(_uri) + _path = u.path + if '@' in _path: + self.ref = _path.rsplit('@', 1)[1] + l = len(self.ref) + 1 + self.url = _uri[:-l] + else: + self.url = _uri + self.ref = default_ref + + def fetch(self): + p = fetch_repo(self.url, self.ref) + return Path(p) + +def main(): + args = docopt.docopt(doc, sys.argv[1:]) + + + root_logger = logging.getLogger() + handlers = root_logger.handlers + for h in handlers: + root_logger.removeHandler(h) + + if args.get('--verbose') or args.get('--debug'): + #logging.root.setLevel(logging.DEBUG) + logging.basicConfig(level=logging.DEBUG, + datefmt='%Y-%m-%d %H:%M:%S', + format='%(asctime)s %(levelname)s:%(message)s') + logging.debug('Verbose mode is enabled') + else: + _info = logging.Formatter('%(message)s') + _default = logging.Formatter('%(levelname)s:%(message)s') + class InfoFormatter(logging.Formatter): + def format(self, record): + if record.levelno == logging.INFO: + return _info.format(record) + else: + return _default.format(record) + h = logging.StreamHandler(sys.stderr) + h.setFormatter(InfoFormatter()) + logging.root.addHandler(h) + logging.root.setLevel(logging.INFO) + + if args.get('--list'): + Deployment.list_deployments() + return + + deployment = Deployment.getDeployment(args) + logging.debug(f'Using deployment type: {deployment.deployment}') + + if args.get('--clean'): + logging.info(f'Cleaning deployment: {deployment.deployment_name}') + deployment.load() + deployment.clean() + elif args.get('--ssh'): + deployment.load() + logging.debug(deployment.access_str()) + os.system(deployment.access_str()) + else: + deployment.deploy() + +class Deployment: + home = os.environ.get('HOME') + '/.teuthology/deploy' + deployment = None + status = None + nameserver = None + dispatcher = None + workers = None + targets = None + domain = None + teuthology_repo = 'https://github.com/ceph/teuthology' + _ceph_cm_ansible_path = None + _libcloud_path = None + + def __init__(self, args): + self.with_args(args) + + def with_args(self, args): + self.args = args + self.deployment_name = args.get('--name') + self.username = args.get('--username') + self.identity_file = args.get('--identity-file') + self.deployment = args.get('--deployment-type') + self.dispatcher = args.get('--dispatcher') + self.workers = args.get('--workers') + self.targets = args.get('--targets') + self.nameserver = args.get('--name-server') + self.domain = args.get('--domain') + self.teuthology_repo = args.get('--teuthology-repo') + self.paddles_repo = args.get('--paddles-repo') + self.pulpito_repo = args.get('--pulpito-repo') + self.ceph_cm_ansible = args.get('--ceph-cm-ansible') + self.libcloud_ssl_cert = args.get('--libcloud-ssl-cert') + libcloud_config = args.get('--libcloud-config') + if libcloud_config: + self._libcloud_path = Path(libcloud_config).absolute() + + logging.debug(f"Init deployment with name '{self.deployment_name}'") + + def getDeployment(args): + d = args.get('--deployment-type') + if d == 'openstack': + return OpenStackDeployment(args) + elif d == 'libvirt': + logging.error('LibVirt deployment is not implemented yet') + exit(1) + elif d == 'ssh' or d == 'direct': + logging.error('Direct ssh deployment is not implemented yet') + exit(1) + else: + logging.error( + f'Unsupported deployment type: {d}, try one of: openstack, libvirt, direct') + exit(1) + + def list_deployments(): + logging.debug(f'Checking directory: {Deployment.home}') + deployments = [_ for _ in os.listdir(Deployment.home)] + if deployments: + logging.info('Found deployments:') + for name in deployments: + logging.info(f'- {name}') + + @property + def home_path(self): + return Path(Deployment.home).joinpath(self.deployment_name) + + @property + def meta_path(self): + return self.home_path.joinpath('meta.json') + + @property + def secrets_path(self): + return self.home_path.joinpath('secrets') + + @staticmethod + def branch_from_repo(repo, default_branch): + """todo: rework""" + repo_and_branch = repo.rsplit('@', 1) + if len(repo_and_branch) > 2: + return repo_and_branch[1] + else: + return default_branch + + @property + def ansible_playbook_path(self): + if self.nameserver: + name = 'teuthology-suse-ns.yml' + else: + name = 'teuthology-suse.yml' + return Path(__file__).absolute().parent.joinpath('ansible', name) + + @property + def ceph_cm_ansible_path(self): + if self._ceph_cm_ansible_path: + return self._ceph_cm_ansible_path + path = Path(self.ceph_cm_ansible) + if path.exists(): + self._ceph_cm_ansible_path = path + else: + repo = Repo(self.ceph_cm_ansible, 'master') + self._ceph_cm_ansible_path = repo.fetch() + return self._ceph_cm_ansible_path + + @property + def ansible_roles(self): + return Path(__file__).absolute().parent.joinpath('ansible/roles') + + @property + def teuthology_git_ref(self): + return self.branch_from_repo(self.teuthology_repo, 'master') + + def prepare_secrets(self): + if not self.secrets_path.exists(): + self.secrets_path.mkdir(parents=True) + paddles_data = dict( + ansible_ssh_user='root', + db_pass='poijpoij', + ) + with open(self.secrets_path.joinpath('paddles.yml'), 'w') as f: + yaml.dump(paddles_data, f) + + @property + def libcloud_yaml_path(self): + if self._libcloud_path: + return self._libcloud_path + path = Path(__file__).absolute().parent.joinpath('libcloud/ovh.cfg.orig') + if path.exists(): + return path + else: + raise Exception(f'No file found by "{path}"') + + def get_meta(self): + meta = dict( + status=self.status, + deployment=self.deployment, + dispatcher=self.dispatcher, + workers=self.workers, + targets=self.targets, + ) + return meta + + def set_meta(self, meta): + self.status = meta.get('status') + self.deployment = meta.get('deployment') + self.dispatcher = meta.get('dispatcher') + self.workers = meta.get('workers') + self.targets = meta.get('targets') + + def deploy(self): + pass + + def clean(self): + pass + + def load(self): + logging.debug(f'Loading meta from {self.meta_path}') + with open(self.meta_path) as f: + meta = json.load(f) + self.set_meta(meta) + + def delete_home(self): + if self.home_path.exists(): + shutil.rmtree(self.home_path) + + def save(self): + if not self.home_path.exists(): + self.home_path.mkdir(parents=True) + with open(self.meta_path, 'w') as f: + json.dump(self.get_meta(), f) + + def access_str(self, user: str = None) -> str: + pass + + +class OpenStackDeployment(Deployment): + server_id = None + access_address = None + floating_address_id = None + def __init__(self, args): + super().__init__(args) + self.cloud = args.get('--os-cloud') + self.deployment_node = f'teuth-{self.deployment_name}' + + assert(self.cloud) + + + def get_meta(self): + meta = super().get_meta() + meta['cloud'] = self.cloud + meta['server_id'] = self.server_id + meta['access_address'] = self.access_address + meta['floating_address_id'] = self.floating_address_id + return meta + + def set_meta(self, meta): + super().set_meta(meta) + self.cloud = meta.get('cloud') + self.server_id = meta.get('server_id') + self.access_address = meta.get('access_address') + self.floating_address_id = meta.get('floating_address_id') + + def get_connect(self): + debug = self.args.get('--debug') + if debug: + openstack.enable_logging(debug=True) + else: + openstack.enable_logging(debug=False) + logging.getLogger("paramiko").setLevel(logging.WARNING) + conn = openstack.connect(self.cloud) + return conn + + + def access_host(self): + return f'{self.username}@{self.access_address}' + + def access_str(self, user: str = None) -> str: + ssh_user = user or self.username + return f'ssh -i {self.identity_file} {ssh_user}@{self.access_address}' + + def deploy(self): + self.conn = self.get_connect() + try: + self.create_server() + logging.debug(f'Connecting to {self.access_host()} using identity {self.identity_file}') + r = Remote(self.access_host(), + host_key=self.identity_file) + r.reconnect(timeout=3*60, sleep_time=10) + logging.debug('get uptime') + uptime = r.sh('uptime') + logging.debug(uptime) + logging.info( + f'Server is created and can be accessed using: {self.access_str()}') + self.save() + # grep ^TEUTHOLOGYBOOT /var/log/cloud-init-output.log + count = 0 + while True: + if r.sh('grep ^TEUTHOLOGYBOOT /var/log/cloud-init-output.log', + check_status=False): + break + if count > 8: + raise Exception('userdata script is not complete') + count += 1 + time.sleep(60) + + # prepare deployment + self.prepare(r) + logging.info(f'Server is ready, login with {self.access_str()}') + except Exception as e: + logging.debug(f'Caught exception: {e}') + if self.args.get('--clean-on-error'): + self.clean() + raise e + + @property + def teuthology_server_yaml_path(self): + return self.home_path.joinpath('teuthology_server.yml') + + def prepare(self, remote): + # make teuthology server yaml + self.prepare_secrets() + teuthology_server = dict( + teuthology_name=self.deployment_name, + teuthology_addr=self.private_address, + nameserver_addr=self.private_address, + machine_type=self.cloud, + secrets_path=str(self.secrets_path), + log_host=self.access_address, + dispatcher=int(self.dispatcher or 0), + workers=int(self.workers or 0), + targets=int(self.targets or 0), + yaml_extra_path=str(self.libcloud_yaml_path), + ansible_ssh_user=self.username, + ansible_ssh_common_args='-o StrictHostKeyChecking=no' + ) + if self.teuthology_git_ref: + teuthology_server.update( + teuthology_git_ref=self.teuthology_git_ref + ) + if self.nameserver: + zone_domain = self.domain or f'{self.cloud}.local' + teuthology_server.update( + nsupdate_web_server=self.private_address, + lab_domain=zone_domain, + zone_name=zone_domain, + zone_domain=zone_domain, + ) + else: + zone_domain = self.domain or 'local' + teuthology_server.update( + lab_domain=zone_domain, + zone_name=zone_domain, + zone_domain=zone_domain, + ) + + teuthology_server_yaml_path = self.home_path.joinpath('teuthology_server.yml') + with open(teuthology_server_yaml_path, 'w') as f: + yaml.dump(teuthology_server, f) + + ceph_cm_ansible_roles = self.ceph_cm_ansible_path.joinpath('roles') + ansible_config = ( + '[defaults]\n' + '#stdout_callback = unixy\n' + 'stdout_callback = yaml\n' + f'roles_path={ceph_cm_ansible_roles}:{self.ansible_roles}\n' + '\n' + '[ssh_connection]\n' + 'pipelining = True\n' + ) + + ansible_config_path = self.home_path.joinpath('teuthology-ansible.cfg') + with open(ansible_config_path, 'w') as f: + f.write(ansible_config) + + ansible_inventory = ( + '[nameserver]\n' + f'{self.access_address}\n' + '[teuthology]\n' + f'{self.access_address}\n' + '[paddles]\n' + f'{self.access_address}\n' + '[pulpito]\n' + f'{self.access_address}\n' + ) + ansible_inventory_path = self.home_path.joinpath('teuthology-inventory') + with open(ansible_inventory_path, 'w') as f: + f.write(ansible_inventory) + + teuthology_role_config_yaml = dict( + author="{{ lookup('env', 'USER') }}", + #ceph_repo: https://github.com/ceph/ceph.git + teuthology_branch="{{ teuthology_git_ref | default('master') }}", + ) + if self.libcloud_ssl_cert: + teuthology_role_config_yaml.update( + libcloud_ssl_cert_file=self.libcloud_ssl_cert, + ) + if self.teuthology_repo: + repo = Repo(self.teuthology_repo, 'master') + teuthology_role_config_yaml.update( + teuthology_repo=repo.url, + teuthology_branch=repo.ref, + ) + + if self.paddles_repo: + repo = Repo(self.paddles_repo, 'master') + teuthology_role_config_yaml.update( + paddles_repo=repo.url, + paddles_branch=repo.ref, + ) + + if self.pulpito_repo: + repo = Repo(self.pulpito_repo, 'master') + teuthology_role_config_yaml.update( + pulpito_repo=repo.url, + pulpito_branch=repo.ref, + ) + + teuthology_config_yaml_path = self.home_path.joinpath('teuthology-role.cfg.yaml') + with open(teuthology_config_yaml_path, 'w') as f: + yaml.dump(teuthology_role_config_yaml, f) + + teuthology_defaults_path = Path(__file__).absolute().parent.joinpath('ansible/teuthology-defaults.yml') + teuthology_vars_path = Path(__file__).absolute().parent.joinpath('ansible/teuthology-vars.yml') + ansible_playbook_command = ( + f'ANSIBLE_CONFIG={ansible_config_path} ansible-playbook -vvv --key-file {self.identity_file}' + f' --user {self.username}' + f' -b' + f' -i {ansible_inventory_path}' + f' -e @{self.teuthology_server_yaml_path}' + f' -e @{teuthology_defaults_path}' + f' -e @{teuthology_config_yaml_path}' + f' -e @{teuthology_vars_path}' + f' {self.ansible_playbook_path}' + ) + logging.info(f'=== will run next command ===\n{ansible_playbook_command}') + + # run ansible + sh(ansible_playbook_command) + + def clean(self): + self.conn = self.get_connect() + self.delete_server() + self.delete_home() + + def create_server(self): + c = self.conn.compute + present_servers = c.servers() + server_names = [_.name for _ in present_servers] + logging.info('Found servers: ' + ', '.join(server_names)) + if self.deployment_node in server_names: + logging.error(f'Deployment server {self.deployment_node} already exists') + exit(1) + image_name = self.args.get('--os-image') + if not image_name: + raise Exception('Image name is undefined, use --os-image option') + image = self.conn.get_image(image_name) + if not image: + raise Exception(f'Image "{image_name}" was not found') + logging.info(f'Found image with id: {image.id}') + flavor_name = self.args.get('--os-flavor') + flavor = self.conn.get_flavor(flavor_name) + if not flavor: + raise Exception(f'Flavor "{flavor_name}" was not found') + logging.info(f'Found flavor with id: {flavor.id}') + keypair_name = self.args.get('--os-keypair') + keypair = self.conn.compute.find_keypair(keypair_name) + if not keypair: + raise Exception(f'Keypair "{keypair_name}" was not found') + logging.info(f'Found keypair with id: {keypair.id}') + + userdata_file = self.args.get('--os-userdata') + if userdata_file: + userdata_path = Path(userdata_file) + else: + userdata_path = Path(__file__).absolute().parent.joinpath('openstack/userdata-ovh.yaml.orig') + userdata = userdata_path.read_text() + + params = dict( + name=self.deployment_node, + image=image.id, + flavor=flavor.id, + key_name=keypair.name, + userdata=userdata, + ) + + floating = self.args.get('--os-floating') + network = self.args.get('--os-network') + if network: + params['network'] = network + + logging.info(f'Creating server with name: {self.deployment_node}') + server = self.conn.create_server(**params) + server_id = server.id + + if server_id: + self.server_id = server_id + + self.save() + + logging.info(f'Created server with id: {server_id}') + + wait_seconds = 10 + timeout = 8 * 60 # seconds + server_status = None + start_time = time.time() + while server_status != 'ACTIVE': + time.sleep(wait_seconds) + server = self.conn.compute.get_server(server_id) + server_status = server.status + if server_status == 'ERROR': + x = self.conn.get_server_by_id(server_id) + if 'fault' in server and 'message' in server['fault']: + raise Exception('Server creation failed with message: ' + f"{x['fault']['message']}") + else: + raise Exception('Unknown failure while creating server: {x}') + + if timeout > (time.time() - start_time): + logging.info(f'Server {server.name} is not active. ' + f'Waiting {wait_seconds} seconds...') + + for i, v in server.addresses.items(): + logging.debug(f'Server network "{i}": {v}') + + ipv4=[x['addr'] for i, nets in server.addresses.items() + for x in nets if x['version'] == 4][0] + self.private_address = ipv4 + logging.info(f'Got IPv4 address for server: {ipv4}') + if floating: + faddr = self.conn.create_floating_ip( + network=floating, + server=server, + fixed_address=ipv4, + wait=True, + ) + ipv4 = faddr['floating_ip_address'] + self.floating_address_id = faddr['id'] + self.access_address = ipv4 + logging.info(f'Server can be accessed using address {ipv4}') + + self.save() + + def delete_server(self): + try: + s = self.conn.compute.get_server(self.server_id) + logging.debug(f'Delete server "{s.name}" with id {s.id}') + self.conn.compute.delete_server(s.id) + except Exception as e: + logging.warning(e) + if self.floating_address_id: + self.conn.delete_floating_ip(self.floating_address_id) + diff --git a/teuthology/deploy/ansible/roles/paddles_nodes/tasks/main.yml b/teuthology/deploy/ansible/roles/paddles_nodes/tasks/main.yml new file mode 100644 index 0000000000..7d686d1aa6 --- /dev/null +++ b/teuthology/deploy/ansible/roles/paddles_nodes/tasks/main.yml @@ -0,0 +1,19 @@ +- name: copy sql populate script if exists + copy: + src: "{{ pop_script }}" + dest: /tmp + when: pop_script is exists +- name: Populate machines + shell: "psql paddles < /tmp/{{ pop_script | basename }}" + # db: paddles + # name: "{{ paddles_user }}" + # password: "{{ db_pass }}" + become_user: postgres + when: pop_script is exists +- name: copy targets psql + template: + src: "targets.psql" + dest: "/tmp/targets.psql" +- name: Populate machines + shell: "psql paddles < /tmp/targets.psql" + become_user: postgres diff --git a/teuthology/deploy/ansible/roles/paddles_nodes/templates/targets.psql b/teuthology/deploy/ansible/roles/paddles_nodes/templates/targets.psql new file mode 100644 index 0000000000..54bc453700 --- /dev/null +++ b/teuthology/deploy/ansible/roles/paddles_nodes/templates/targets.psql @@ -0,0 +1,7 @@ +begin transaction; +insert into nodes (name,machine_type,is_vm,locked,up) values +{% for i in range(1, targets + 1) %} +('target-{{ teuthology_name }}-{{ "%03d" % i }}.{{ lab_domain }}', '{{ machine_type}}', TRUE, FALSE, TRUE){% if i == targets %};{% else %},{% endif %} +{% endfor %} +commit transaction + diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/defaults/main.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/defaults/main.yml new file mode 100644 index 0000000000..9fd05afb69 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/defaults/main.yml @@ -0,0 +1,3 @@ +--- +zone_name: "nbg.suse.de" +zone_secret: "JdpAxNnefZ40iMw8jALOrbituj78fKOZsfhINk3Ay/8eXZg/Sdghg+JhhFOvkf6YJ2eC43gpfdgqxkuNiWzb9w==" diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/dnssec-keygen.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/dnssec-keygen.yml new file mode 100644 index 0000000000..e6f2441eb8 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/dnssec-keygen.yml @@ -0,0 +1,34 @@ +#Moved dnssec key generation from deploy-teuthology script to the ansible task due to HMAC-MD5 being deprecated on Tumbleweed. +- name: Generate new keys + shell: "/usr/sbin/dnssec-keygen -r /dev/urandom -a HMAC-MD5 -b 512 -n HOST '{{ zone_name }}'" + register: + dns_keygen + +- name: Get prikey contents + slurp: + src: "{{ dns_keygen.stdout }}.private" + register: prikey_out + +- name: Set key vars + set_fact: + dns_key: "{{ dns_keygen.stdout }}" + pubkey_name: "{{ dns_keygen.stdout }}.key" + prikey_name: "{{ dns_keygen.stdout }}.private" + zone_secret: "{{ (prikey_out.content | b64decode | from_yaml).Key }}" + +- name: Define named.conf key data + set_fact: + named_conf_key: | + key "{{ zone_name }}." { + algorithm hmac-md5; + secret "{{ zone_secret }}"; + }; + +- name: Fetch the keys to secrets local path + fetch: + src: "{{ ansible_env.HOME }}/{{ item }}" + dest: "{{ secrets_path }}/" + flat: true + loop: + - "{{ pubkey_name }}" + - "{{ prikey_name }}" diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/main.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/main.yml new file mode 100644 index 0000000000..13f224872c --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/main.yml @@ -0,0 +1,151 @@ +# Install and update system packages +- import_tasks: packages.yml + tags: + - packages + +#- name: generate dnssec key +# import_tasks: dnssec-keygen.yml +# tags: +# - dnssec-keygen + +- name: Generate tsig key + import_tasks: tsig-keygen.yml + tags: + - tsig-keygen + +- name: Enable and start ntpd + service: + name: ntpd + state: started + enabled: yes + tags: + - always + when: ansible_os_family == "Suse" + +- name: Enable and start ntp for Debian based distro + service: + name: ntp + state: started + enabled: yes + when: ansible_os_family == "Debian" + +- name: nameserver list from resolv.conf + shell: | + grep -E -v '^\s*\#' /etc/resolv.conf | grep nameserver | sed -E 's/^.*nameserver\s+([^[:space:]\#]+).*$/\1/g' + register: resolv_conf_nameservers +- name: name names + set_fact: nslist="{{resolv_conf_nameservers.stdout_lines}}" +- name: printout {{ nslist }} + debug: var=nslist + +## We cannot use named.conf.include directly anymore +## because on opensuse it is generated automatically, +## that is why we have to use NAMED_CONF_INCLUDE_FILES +# +#- name: Check that named.conf.include exists +# stat: +# path: /etc/named.conf.include +# register: named_conf_include +# +#- name: Create the file, if it doesnt exist already +# file: +# path: /etc/named.conf.include +# state: touch +# when: named_conf_include.stat.exists == False +# +#- name: add zone config to named.conf.include +# blockinfile: +# create: yes +# block: "{{ lookup('template', 'named.conf.j2') }}" +# path: '/etc/named.conf.include' +# +- name: Create named.conf for the domain + template: + src: "named.conf.j2" + dest: "/etc/named.d/{{ zone_name }}.conf" + +- name: Set NAMED_CONF_INCLUDE_FILES in /etc/sysconfig/named + replace: + backup: yes + path: /etc/sysconfig/named + regexp: '^(NAMED_CONF_INCLUDE_FILES)=.*$' + replace: '\1="{{ zone_name }}.conf"' + +- name: copy zone db file + template: + src: "zone.db.j2" + dest: "/var/lib/named/{{ zone_name }}.db" +- name: set forwarders + lineinfile: + backrefs: yes + regexp: '#forwarders' + state: present + path: /etc/named.conf + line: | + forwarders { {% for i in nslist %}{{ i }}; {% endfor %} }; +- name: Allow recursion + lineinfile: + backup: yes + state: present + dest: /etc/named.conf + insertafter: 'options {' + line: "\tallow-recursion { any; };" +- name: Restart named + service: + name: named + state: restarted + enabled: yes + tags: + - always + +- name: Add lab domain to DNS static search list + replace: + backup: yes + path: /etc/sysconfig/network/config + regexp: '^(NETCONFIG_DNS_STATIC_SEARCHLIST)=.*$' + replace: '\1="{{ lab_domain }}"' + +- name: Set DNS forwarder to bind + replace: + backup: yes + path: /etc/sysconfig/network/config + regexp: '^(NETCONFIG_DNS_FORWARDER)=.*$' + replace: '\1="bind"' + +- name: Force adjusting the /etc/resolv.conf + shell: | + netconfig update -f + +- name: Make nsupdate test script + blockinfile: + path: /tmp/nsupdate-test-create.txt + create: yes + marker: "; {mark}" + block: | + server master.ddns.{{ lab_domain }} + zone {{ lab_domain }} + update delete local.ddns.{{ lab_domain }}. A + update add local.ddns.{{ lab_domain }}. 600 A 127.0.0.1 + show + send + +- name: Delete dns record test script + blockinfile: + path: /tmp/nsupdate-test-delete.txt + marker: "; {mark}" + create: yes + block: | + server master.ddns.{{ lab_domain }} + zone {{ lab_domain }} + update delete local.ddns.{{ lab_domain }}. A + show + send + +- name: Check nsupdate setup + shell: | + nsupdate -k {{ pubkey_name }} -v /tmp/nsupdate-test-create.txt +- name: Check dns + shell: | + host local.ddns.{{ lab_domain }} + ping -c 1 local.ddns + diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/packages.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/packages.yml new file mode 100644 index 0000000000..92a3be34b5 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/packages.yml @@ -0,0 +1,37 @@ +--- +- name: Include nameserver package list + include_vars: packages_redhat.yml + when: ansible_os_family == "RedHat" + +- name: Include nameserver package list + include_vars: packages_suse.yml + when: ansible_os_family == "Suse" + +- name: Include nameserver package list + include_vars: packages_ubuntu.yml + when: ansible_distribution == "Ubuntu" + +- name: Install and update packages via yum + yum: + name: "{{ packages }}" + state: latest + enablerepo: epel + when: ansible_pkg_mgr == "yum" + +- name: Install and update packages via zypper + zypper: + name: "{{ packages }}" + state: latest + update_cache: yes + when: ansible_pkg_mgr == "zypper" + tags: + - packages + +- name: Install and update packages via apt + apt: + name: "{{ packages }}" + state: latest + update_cache: yes + when: ansible_pkg_mgr == "apt" + tags: + - packages diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/tsig-keygen.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/tsig-keygen.yml new file mode 100644 index 0000000000..ce41a70a79 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/tasks/tsig-keygen.yml @@ -0,0 +1,24 @@ +- name: Generate TSIG key + shell: "tsig-keygen {{ zone_name }}." + register: tsig_keygen + +- name: Set key vars + set_fact: + tsig_key: "{{ tsig_keygen.stdout }}" + pubkey_name: "{{ teuthology_name }}.{{ zone_name }}.key" + named_conf_key: | + {{ tsig_keygen.stdout }} + +- name: Save tsig key data to secrets local path + local_action: + module: copy + content: "{{ tsig_key }}" + dest: "{{ secrets_path }}/{{ pubkey_name }}" + # specifically disable become to avoid sudo on localhost + vars: + ansible_become: false + +- name: Copy tsig key to remote host + copy: + src: "{{ secrets_path }}/{{ pubkey_name }}" + dest: "{{ pubkey_name }}" diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/named.conf.j2 b/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/named.conf.j2 new file mode 100644 index 0000000000..2377e4190d --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/named.conf.j2 @@ -0,0 +1,7 @@ +{{ named_conf_key }} + +zone "{{ zone_name }}" { + type master; + file "/var/lib/named/{{ zone_name }}.db"; + allow-update { key "{{ zone_name }}."; }; +}; diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/zone.db.j2 b/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/zone.db.j2 new file mode 100644 index 0000000000..5398b34c6f --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/templates/zone.db.j2 @@ -0,0 +1,21 @@ +$ORIGIN . +$TTL 604800 ; 1 week +{{ zone_name }} IN SOA {{ zone_name }}. root.{{ zone_name }}. ( + 503201902 ; serial + 172800 ; refresh (2 days) + 14400 ; retry (4 hours) + 3628800 ; expire (6 weeks) + 604800 ; minimum (1 week) + ) + + NS master.ddns.{{ zone_name }}. +{% for ns in nslist %} +ns{{ loop.index }} NS {{ ns }} +{% endfor %} +$ORIGIN {{ zone_name }}. +ci A {{ teuthology_addr }} +$ORIGIN ddns.{{ zone_name }}. +master A {{ nameserver_addr }} +$ORIGIN {{ zone_name }}. +www CNAME master.ddns + diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_redhat.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_redhat.yml new file mode 100644 index 0000000000..ee3222fdec --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_redhat.yml @@ -0,0 +1,19 @@ +--- +packages: + ## misc tools + - vim + - wget + - mlocate + - git + - redhat-lsb-core + ## bind-specific packages + - bind + - bind-utils + ## firewall + - firewalld + ## monitoring + - nrpe + - nagios-plugins-all + ## for NTP + - ntp + - ntpdate diff --git a/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_suse.yml b/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_suse.yml new file mode 100644 index 0000000000..341e68ff41 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_nameserver/vars/packages_suse.yml @@ -0,0 +1,21 @@ +--- +packages: + ## misc tools + - vim + - wget + - mlocate + - git + - lsb + ## bind-specific packages + - bind + - bind-utils + ## firewall + - firewalld + ## monitoring + - nrpe + - nagios-plugins-all + ## for NTP + - ntp + #- ntpdate + # do we really need selinux on opensuse? + - python-selinux diff --git a/teuthology/deploy/ansible/roles/teuthology_users/tasks/main.yml b/teuthology/deploy/ansible/roles/teuthology_users/tasks/main.yml new file mode 100644 index 0000000000..7329ceaf44 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_users/tasks/main.yml @@ -0,0 +1,32 @@ +- name: Generate a key + shell: | + printf "\n" | ssh-keygen -m PEM -t rsa -C "{{ teuthology_execution_user }}@{{ teuthology_name }}" -N '' -q + become_user: "{{ item }}" + with_items: + - "{{ teuthology_execution_user }}" + +- name: "Grab {{ teuthology_execution_user }} public key" + shell: | + cat ~/.ssh/id_rsa.pub + become_user: "{{ teuthology_execution_user }}" + register: cat_worker_id_rsa_pub + +- set_fact: + worker_pub_key: "{{ cat_worker_id_rsa_pub.stdout }}" + +- name: Update teuthology.conf + blockinfile: + block: | + ssh_authorized_keys: + - "{{ worker_pub_key }}" + path: "/etc/teuthology.yaml" + +- name: Add your key to authorized + lineinfile: + create: yes + path: "/home/{{ item }}/.ssh/authorized_keys" + line: "{{ lookup(\"file\", \"{{ lookup('env', 'HOME') }}/.ssh/id_rsa.pub\") }}" + owner: "{{ item }}" + with_items: + - "{{ teuthology_execution_user }}" + - "{{ teuthology_scheduler_user }}" diff --git a/teuthology/deploy/ansible/roles/teuthology_workers/defaults/main.yml b/teuthology/deploy/ansible/roles/teuthology_workers/defaults/main.yml new file mode 100644 index 0000000000..19e59eaba8 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_workers/defaults/main.yml @@ -0,0 +1,3 @@ +teuthology_execution_user: teuthworker +libcloud_ssl_cert_file: '' + diff --git a/teuthology/deploy/ansible/roles/teuthology_workers/tasks/main.yml b/teuthology/deploy/ansible/roles/teuthology_workers/tasks/main.yml new file mode 100644 index 0000000000..610dc15e81 --- /dev/null +++ b/teuthology/deploy/ansible/roles/teuthology_workers/tasks/main.yml @@ -0,0 +1,58 @@ +- name: Enable and start beanstalkd + service: + name: beanstalkd + state: started + enabled: yes + tags: + - always + +- name: Start workers + shell: | + source virtualenv/bin/activate + {% if libcloud_ssl_cert_file %} + export SSL_CERT_FILE={{ libcloud_ssl_cert_file }} + {% endif %} + echo "I'm {{ teuthology_execution_user }}" + whoami + bash docs/_static/worker_start.sh {{ machine_type }} {{ workers }} + args: + executable: /bin/bash + chdir: /home/{{ teuthology_execution_user }}/src/teuthology_main + become_user: "{{ teuthology_execution_user }}" + when: workers > 0 + +- name: Tweak ssh_config + blockinfile: + create: yes + block: | + Host * + StrictHostKeyChecking no + UserKnownHostsFile=/dev/null + + path: "/home/{{ teuthology_execution_user }}/.ssh/config" + become_user: "{{ teuthology_execution_user }}" + +- name: Add SSL_CERT_FILE to .bashrc + blockinfile: + create: yes + block: | + export SSL_CERT_FILE={{ libcloud_ssl_cert_file }} + + path: "/home/{{ teuthology_execution_user }}/.bashrc" + become_user: "{{ teuthology_execution_user }}" + when: libcloud_ssl_cert_file != "" + +- name: Start dispatcher + shell: | + source virtualenv/bin/activate + {% if libcloud_ssl_cert_file %} + export SSL_CERT_FILE={{ libcloud_ssl_cert_file }} + {% endif %} + mkdir -p /home/{{ teuthology_execution_user }}/logs + teuthology-dispatcher -v --tube {{ machine_type }} --log-dir /home/{{ teuthology_execution_user }}/logs >> /home/{{ teuthology_execution_user }}/teuthology-dispatcher.log 2>&1 & + + args: + executable: /bin/bash + chdir: /home/{{ teuthology_execution_user }}/src/teuthology_main + become_user: "{{ teuthology_execution_user }}" + when: dispatcher > 0 diff --git a/teuthology/deploy/ansible/teuthology-defaults.yml b/teuthology/deploy/ansible/teuthology-defaults.yml new file mode 100644 index 0000000000..a54276359b --- /dev/null +++ b/teuthology/deploy/ansible/teuthology-defaults.yml @@ -0,0 +1,9 @@ +--- +teuthology_repo: https://github.com/ceph/teuthology.git +paddles_repo: https://github.com/ceph/paddles.git +pulpito_repo: https://github.com/ceph/pulpito.git +ceph_repo: https://github.com/ceph/ceph.git + +teuthology_branch: main +paddles_branch: main +pulpito_branch: main diff --git a/teuthology/deploy/ansible/teuthology-suse-ns.yml b/teuthology/deploy/ansible/teuthology-suse-ns.yml new file mode 100644 index 0000000000..c572baa8ea --- /dev/null +++ b/teuthology/deploy/ansible/teuthology-suse-ns.yml @@ -0,0 +1,25 @@ +--- +- hosts: teuthology + strategy: free + pre_tasks: + - name: Add teuthology repo + zypper_repository: + name: teuthology + repo: "{{ item }}" + auto_import_keys: yes + disable_gpg_check: yes + state: present + with_items: "{{ teuthology_rpm_repo[ansible_distribution][ansible_distribution_version] }}" + when: ansible_os_family == "Suse" + roles: + - ansible-managed + - common + - paddles + - paddles_nodes + - pulpito + - teuthology + - teuthology_workers + - teuthology_nameserver + - teuthology_users + - nsupdate_web + become: true diff --git a/teuthology/deploy/ansible/teuthology-suse.yml b/teuthology/deploy/ansible/teuthology-suse.yml new file mode 100644 index 0000000000..7cd71039bd --- /dev/null +++ b/teuthology/deploy/ansible/teuthology-suse.yml @@ -0,0 +1,30 @@ +--- +- hosts: teuthology + strategy: free + pre_tasks: + - name: Add teuthology repo + zypper_repository: + name: teuthology + repo: "{{ item }}" + auto_import_keys: yes + disable_gpg_check: yes + state: present + with_items: "{{ teuthology_rpm_repo[ansible_distribution][ansible_distribution_version] }}" + when: ansible_os_family == "Suse" + roles: + #- { role: 'ansible/roles/ansible-managed' } + #- { role: 'ansible/roles/common' } + #- { role: 'ansible/roles/paddles' } + #- { role: 'ansible/roles/pulpito' } + #- { role: 'ansible/roles/teuthology' } + - ansible-managed + - common + - paddles + - paddles_nodes + - pulpito + - teuthology + - teuthology_workers + - teuthology_users + #- nameserver + #- nsupdate_web + become: true diff --git a/teuthology/deploy/ansible/teuthology-vars.yml b/teuthology/deploy/ansible/teuthology-vars.yml new file mode 100644 index 0000000000..dc5bcfa4c1 --- /dev/null +++ b/teuthology/deploy/ansible/teuthology-vars.yml @@ -0,0 +1,29 @@ +--- +teuthology_rpm_repo: + 'openSUSE Leap': + '42.3': + - https://download.opensuse.org/repositories/filesystems:/ceph:/teuthology/openSUSE_Leap_42.3/ + '15.1': + - https://download.opensuse.org/repositories/filesystems:/ceph:/teuthology/openSUSE_Leap_15.1/ + '15.2': + - https://download.opensuse.org/repositories/filesystems:/ceph:/teuthology/openSUSE_Leap_15.2/ + '15.3': + - https://download.opensuse.org/repositories/filesystems:/ceph:/teuthology/openSUSE_Leap_15.3/ +paddles_address: http://127.0.0.1:8080 +#pulpito_address: http://{{ ansible_hostname }}:8081 +pulpito_address: http://{{ inventory_hostname }}:8081 + +nsupdate_url: 'http://localhost:8888/update' +nsupdate_web_port: '8888' +#yaml_extra_path: "libcloud/{{ machine_type }}.cfg" +pop_script: "roles/paddles_nodes/files/populate_nodes.psql" + +named_conf_dir: "/var/lib/named" +named_conf_data_dir: "/var/lib/named/data" +named_conf_zones_path: "/var/lib/named/zones" +named_conf_recursion: "no" + +teuthology_ceph_git_base_url: 'http://github.com/ceph/' +teuthology_scheduler_user: runner +teuthology_execution_user: worker +teuthology_yaml_extra: "{{ lookup('template', '{{ yaml_extra_path }}') }}" diff --git a/teuthology/deploy/libcloud/ecp.cfg.orig b/teuthology/deploy/libcloud/ecp.cfg.orig new file mode 100644 index 0000000000..6da49a9749 --- /dev/null +++ b/teuthology/deploy/libcloud/ecp.cfg.orig @@ -0,0 +1,107 @@ +use_shaman: true +check_package_signatures: false +suite_verify_ceph_hash: false +canonical_tags: true +# comment the next line to enable --teuthology-branch +#teuthology_path: "/home/{{ teuthology_execution_user }}/src/teuthology_master" +ceph_git_url: "{{ ceph_repo }}" +nsupdate_url: "http://localhost:{{ nsupdate_web_port }}/update" +libcloud: + ovh_fix: &ovh_fix_ifcfg + | + cat > /tmp/ifcfg << EOF + BOOTPROTO=dhcp + MTU= + REMOTE_IPADDR= + STARTMODE=auto + ETHTOOL_OPTIONS= + USERCONTROL=no + EOF + + cat > /tmp/fix-ifcfg << EOF + ETH=\$(ip route list | grep "scope link" | cut -f 3 -d ' ') + cp /etc/sysconfig/network/ifcfg-\$ETH /etc/sysconfig/network/ifcfg-\$ETH.backup + cp /tmp/ifcfg /etc/sysconfig/network/ifcfg-\$ETH + ifdown \$ETH + ifup \$ETH + EOF + + bash /tmp/fix-ifcfg + common: + resolv_conf: &resolv_conf + | + cat > /etc/resolv.conf << EOF + search {{ lab_domain }} + nameserver {{ nameserver_addr }} + EOF + sed -Ei 's/(NETCONFIG_DNS_STATIC_SEARCHLIST)=""/\1="{{ lab_domain }}"/' /etc/sysconfig/network/config + sed -Ei 's/(NETCONFIG_DNS_STATIC_SERVERS)=""/\1="{{ nameserver_addr }}"/' /etc/sysconfig/network/config + sudoer_user: &sudoer_user + | + cat > /etc/sudoers.d/teuthology-user << EOF + # User rules for teuthology + ubuntu ALL=(ALL) NOPASSWD:ALL + EOF + manage_resolv_conf: &manage_resolv_conf + manage_resolv_conf: true + nameservers: + - "{{ nameserver_addr }}" + searchdomains: + - "{{ lab_domain }}" + providers: + ecp: # This string is the 'machine type' value you will use when locking these nodes + userdata: + "sle-15.1": &sle15 + runcmd: + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ chrony || true + - systemctl enable chronyd.service || true + - systemctl start chronyd.service || true + "sle-15.2": *sle15 + "sle-15.3": *sle15 + "opensuse-15.1": &leap15 + runcmd: + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ chrony || true + - systemctl enable chronyd.service || true + - systemctl start chronyd.service || true + "opensuse-15.2": *leap15 + "opensuse-15.3": *leap15 + "sle-12.3": + bootcmd: + - SuSEfirewall2 stop + - | + sed -i '/127.0.0.1/i 127.0.0.1 {% raw %}{{fqdn}} {{hostname}}{% endraw %}' /etc/cloud/templates/hosts.suse.tmpl + runcmd: + - *resolv_conf + - *sudoer_user + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ ntp || true + - | + if ! grep '^server' /etc/ntp.conf ; then + for i in 0 1 2 3 ; do + echo "server $i.opensuse.pool.ntp.org iburst" >> /etc/ntp.conf + done + fi + - systemctl enable ntpd.service + - systemctl restart ntpd.service + + allow_networks: 'sesci' + exclude_sizes: 'caasp.*|cloud.*|win-.*' + exclude_image: '.*-TEST-.*' + ssh_interface: 'private_ips' + driver: openstack + driver_args: # driver args are passed directly to the libcloud driver + ex_domain_name: 'Default' + ex_force_auth_url: 'https://engcloud.prv.suse.net:5000/v2.0/tokens' + ex_force_auth_version: '2.0_password' + #ex_domain_name: 'ldap_users' + #ex_force_auth_url: 'https://engcloud.prv.suse.net:5000/v3/auth/tokens' + #ex_force_auth_version: '3.x_password' + ex_force_service_region: 'CustomRegion' + #api_version: '2.1' + ex_tenant_name: 'ses' + username: 'CHANGE_USERNAME' + password: 'CHANGE_PASSWORD' diff --git a/teuthology/deploy/libcloud/nbg.cfg.orig b/teuthology/deploy/libcloud/nbg.cfg.orig new file mode 100644 index 0000000000..447356c349 --- /dev/null +++ b/teuthology/deploy/libcloud/nbg.cfg.orig @@ -0,0 +1,25 @@ +use_shaman: true +check_package_signatures: false +suite_verify_ceph_hash: false +# comment the next line to enable --teuthology-branch +#teuthology_path: "/home/{{ teuthology_execution_user }}/src/teuthology_master" +ceph_git_url: "{{ ceph_repo }}" +nsupdate_url: "http://localhost:{{ nsupdate_web_port }}/update" +libcloud: + providers: + nbg: # This string is the 'machine type' value you will use when locking these nodes + allow_networks: 'fixed' + exclude_sizes: '^(c|d)[0-9]\.|manila.*' + ssh_interface: 'private_ips' + driver: openstack + driver_args: # driver args are passed directly to the libcloud driver + username: 'CHANGE_USERNAME' + password: 'CHANGE_PASSWORD' + ex_tenant_name: 'ses' + #ex_domain_name: 'ldap_users' + ex_domain_name: 'Default' + ex_force_service_region: 'CustomRegion' + ex_force_auth_url: 'https://dashboardp3.cloud.suse.de:5000/v2.0/tokens' + ex_force_auth_version: '2.0_password' + #ex_force_auth_url: 'https://dashboardp3.cloud.suse.de:5000/v3/tokens' + #ex_force_auth_version: '3.x_password' diff --git a/teuthology/deploy/libcloud/ovh.cfg.orig b/teuthology/deploy/libcloud/ovh.cfg.orig new file mode 100644 index 0000000000..7fe3f1c2b7 --- /dev/null +++ b/teuthology/deploy/libcloud/ovh.cfg.orig @@ -0,0 +1,161 @@ +use_shaman: true +check_package_signatures: false +# next is required to enable '--newest' teuthology-suite argument +suite_verify_ceph_hash: true +canonical_tags: true +# comment the next line to enable --teuthology-branch +#teuthology_path: "/home/{{ teuthology_execution_user }}/src/teuthology_master" +ceph_git_url: "{{ ceph_repo }}" +nsupdate_url: "http://localhost:{{ nsupdate_web_port }}/update" +libcloud: + ovh_fix: &ovh_fix_ifcfg + | + cat > /tmp/ifcfg << EOF + BOOTPROTO=dhcp + MTU= + REMOTE_IPADDR= + STARTMODE=auto + ETHTOOL_OPTIONS= + USERCONTROL=no + EOF + + cat > /tmp/fix-ifcfg << EOF + ETH=\$(ip route list | grep "scope link" | cut -f 3 -d ' ') + cp /etc/sysconfig/network/ifcfg-\$ETH /etc/sysconfig/network/ifcfg-\$ETH.backup + cp /tmp/ifcfg /etc/sysconfig/network/ifcfg-\$ETH + ifdown \$ETH + ifup \$ETH + EOF + + bash /tmp/fix-ifcfg + common: + resolv_conf: &resolv_conf + | + cat > /etc/resolv.conf << EOF + search {{ lab_domain }} + nameserver {{ nameserver_addr }} + EOF + manage_resolv_conf: &manage_resolv_conf + manage_resolv_conf: true + nameservers: + - "{{ nameserver_addr }}" + searchdomains: + - "{{ lab_domain }}" + userdata: &userdata + "centos-8.1": ¢os8 + runcmd: + - *resolv_conf + "centos-8.2": *centos8 + "centos-8.3": *centos8 + "opensuse-15.1": &suse15 + runcmd: + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ chrony || true + - systemctl enable chronyd.service || true + - systemctl start chronyd.service || true + "opensuse-15.2": *suse15 + "opensuse-15.3": *suse15 + "sle-15.1": *suse15 + "sle-15.2": *suse15 + "sle-15.3": *suse15 + "sle-12.3": + bootcmd: + - SuSEfirewall2 stop + runcmd: + - *ovh_fix_ifcfg + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ ntpd || true + - | + if ! grep '^server' /etc/ntp.conf ; then + for i in 0 1 2 3 ; do + echo "server $i.opensuse.pool.ntp.org iburst" >> /etc/ntp.conf + done + fi + - systemctl enable ntpd.service + - systemctl restart ntpd.service + driver_args: &driver_args # driver args are passed directly to the libcloud driver + #ex_force_service_region: 'SBG5' + #ex_force_auth_url: 'https://auth.cloud.ovh.net/v2.0/tokens' + #ex_force_auth_version: '2.0_password' + ex_force_auth_url: 'https://auth.cloud.ovh.net/v3/auth/tokens' + ex_force_auth_version: '3.x_password' + ex_tenant_name: 'CHANGE_ME' + username: 'CHANGE_ME' + password: 'CHANGE_ME' + + providers: + # This string is the 'machine type' value you will use when locking these nodes + ovh: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'GRA5' + <<: *driver_args + bhs: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'BHS3' + <<: *driver_args + gra: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'GRA5' + <<: *driver_args + waw: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'WAW1' + <<: *driver_args + de: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'DE1' + <<: *driver_args + uk: + userdata: *userdata + driver: openstack + driver_args: + ex_force_service_region: 'UK1' + <<: *driver_args + +openstack: + clone: git clone {{ teuthology_repo }} + user-data: "teuthology/openstack/openstack-{os_type}-{os_version}-user-data.txt" + ip: "{{ teuthology_addr }}" + nameserver: "{{ nameserver_addr }}" + selfname: "{{ teuthology_name }}" + keypair: teuth-ci + server_name: teuth-ci + server_group: teuth-ci + worker_group: teuth-ci-worker + package_repo: teuth-ci-repo + # + # OpenStack has predefined machine sizes (called flavors) + # For a given job requiring N machines, the following will select + # the smallest flavor that satisfies these requirements. For instance + # If there are three flavors + # + # F1 (10GB disk, 2000MB RAM, 1CPU) + # F2 (100GB disk, 7000MB RAM, 1CPU) + # F3 (50GB disk, 7000MB RAM, 1CPU) + # + # and machine: { disk: 40, ram: 7000, cpus: 1 }, F3 will be chosen. + # F1 does not have enough RAM (2000 instead of the 7000 minimum) and + # although F2 satisfies all the requirements, it is larger than F3 + # (100GB instead of 50GB) and presumably more expensive. + # + machine: + disk: 20 # GB + ram: 4000 # MB + cpus: 1 + volumes: + count: 0 + size: 1 # GB + subnet: 51.68.80.0/20 + diff --git a/teuthology/deploy/libcloud/sbg.cfg.orig b/teuthology/deploy/libcloud/sbg.cfg.orig new file mode 100644 index 0000000000..e7f3833487 --- /dev/null +++ b/teuthology/deploy/libcloud/sbg.cfg.orig @@ -0,0 +1,114 @@ +use_shaman: true +check_package_signatures: false +suite_verify_ceph_hash: false +canonical_tags: true +# comment the next line to enable --teuthology-branch +#teuthology_path: "/home/{{ teuthology_execution_user }}/src/teuthology_master" +ceph_git_url: "{{ ceph_repo }}" +nsupdate_url: "http://localhost:{{ nsupdate_web_port }}/update" +libcloud: + ovh_fix: &ovh_fix_ifcfg + | + cat > /tmp/ifcfg << EOF + BOOTPROTO=dhcp + MTU= + REMOTE_IPADDR= + STARTMODE=auto + ETHTOOL_OPTIONS= + USERCONTROL=no + EOF + + cat > /tmp/fix-ifcfg << EOF + ETH=\$(ip route list | grep "scope link" | cut -f 3 -d ' ') + cp /etc/sysconfig/network/ifcfg-\$ETH /etc/sysconfig/network/ifcfg-\$ETH.backup + cp /tmp/ifcfg /etc/sysconfig/network/ifcfg-\$ETH + ifdown \$ETH + ifup \$ETH + EOF + + bash /tmp/fix-ifcfg + common: + resolv_conf: &resolv_conf + | + cat > /etc/resolv.conf << EOF + search {{ lab_domain }} + nameserver {{ nameserver_addr }} + EOF + manage_resolv_conf: &manage_resolv_conf + manage_resolv_conf: true + nameservers: + - "{{ nameserver_addr }}" + searchdomains: + - "{{ lab_domain }}" + providers: + sbg: # This string is the 'machine type' value you will use when locking these nodes + userdata: + "sle-15.1": + runcmd: + - *ovh_fix_ifcfg + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ chrony || true + - systemctl enable chronyd.service || true + - systemctl start chronyd.service || true + "sle-12.3": + bootcmd: + - SuSEfirewall2 stop + runcmd: + - *ovh_fix_ifcfg + - *resolv_conf + - zypper in -y git wget rsyslog || true + - zypper in -y lsb-release make gcc gcc-c++ ntpd || true + - | + if ! grep '^server' /etc/ntp.conf ; then + for i in 0 1 2 3 ; do + echo "server $i.opensuse.pool.ntp.org iburst" >> /etc/ntp.conf + done + fi + - systemctl enable ntpd.service + - systemctl restart ntpd.service + driver: openstack + driver_args: # driver args are passed directly to the libcloud driver + ex_force_service_region: 'SBG5' + #ex_force_auth_url: 'https://auth.cloud.ovh.net/v2.0/tokens' + #ex_force_auth_version: '2.0_password' + ex_force_auth_url: 'https://auth.cloud.ovh.net/v3/auth/tokens' + ex_force_auth_version: '3.x_password' + ex_tenant_name: 'CHANGE_ME' + username: 'CHANGE_ME' + password: 'CHANGE_ME' +openstack: + clone: git clone {{ teuthology_repo }} + user-data: teuthology/openstack/openstack-{os_type}-{os_version}-user-data.txt + ip: {{ teuthology_addr }} + nameserver: {{ nameserver_addr }} + selfname: {{ teuthology_name }} + keypair: teuth-ci + server_name: teuth-ci + server_group: teuth-ci + worker_group: teuth-ci-worker + package_repo: teuth-ci-repo + # + # OpenStack has predefined machine sizes (called flavors) + # For a given job requiring N machines, the following will select + # the smallest flavor that satisfies these requirements. For instance + # If there are three flavors + # + # F1 (10GB disk, 2000MB RAM, 1CPU) + # F2 (100GB disk, 7000MB RAM, 1CPU) + # F3 (50GB disk, 7000MB RAM, 1CPU) + # + # and machine: { disk: 40, ram: 7000, cpus: 1 }, F3 will be chosen. + # F1 does not have enough RAM (2000 instead of the 7000 minimum) and + # although F2 satisfies all the requirements, it is larger than F3 + # (100GB instead of 50GB) and presumably more expensive. + # + machine: + disk: 20 # GB + ram: 4000 # MB + cpus: 1 + volumes: + count: 0 + size: 1 # GB + subnet: 51.68.80.0/20 + diff --git a/teuthology/deploy/openstack/userdata-cloud.yaml.orig b/teuthology/deploy/openstack/userdata-cloud.yaml.orig new file mode 100644 index 0000000000..772884c9f5 --- /dev/null +++ b/teuthology/deploy/openstack/userdata-cloud.yaml.orig @@ -0,0 +1,16 @@ +#cloud-config + +#chpasswd: +# list: | +# root:CHANGEME +# expire: False +# +#disable_root: false + +runcmd: + - [ sh, -c, echo "========= Teuthology setup started =========" ] + - zypper -n --gpg-auto-import-keys refresh + - zypper -n --gpg-auto-import-keys install -y python python-virtualenv python-xml ansible + #- zypper -n --gpg-auto-import-keys update --auto-agree-with-licenses + +final_message: "TEUTHOLOGYBOOT $UPTIME" diff --git a/teuthology/deploy/openstack/userdata-ecp.yaml.orig b/teuthology/deploy/openstack/userdata-ecp.yaml.orig new file mode 100644 index 0000000000..0a250ed23b --- /dev/null +++ b/teuthology/deploy/openstack/userdata-ecp.yaml.orig @@ -0,0 +1,28 @@ +#cloud-config + +#chpasswd: +# list: | +# root:CHANGEME +# expire: False + +disable_root: false + +bootcmd: + - rm /etc/resolv.conf +runcmd: + - [ sh, -c, echo "========= Teuthology setup started =========" ] + - | + netconfig update -f + - | + for i in $(seq 1 30) ; do + ping -q -c 1 download.suse.de && break + sleep 10 + done + - | + source /etc/os-release + zypper -n --gpg-auto-import-keys addrepo http://download.suse.de/ibs/SUSE:/CA/openSUSE_Leap_${VERSION_ID}/ suse-ca + - zypper -n --gpg-auto-import-keys refresh + - zypper -n --gpg-auto-import-keys install -y python python-virtualenv python-xml ansible + - zypper -n --gpg-auto-import-keys install -y ca-certificates-suse + +final_message: "TEUTHOLOGYBOOT $UPTIME" diff --git a/teuthology/deploy/openstack/userdata-nbg.yaml.orig b/teuthology/deploy/openstack/userdata-nbg.yaml.orig new file mode 100644 index 0000000000..2573565b1f --- /dev/null +++ b/teuthology/deploy/openstack/userdata-nbg.yaml.orig @@ -0,0 +1,14 @@ +#cloud-config + +#chpasswd: +# list: | +# root:CHANGEME +# expire: False + +runcmd: + - [ sh, -c, echo "========= Teuthology setup started =========" ] + - zypper --non-interactive --gpg-auto-import-keys refresh + - zypper --non-interactive --gpg-auto-import-keys install -y python python-virtualenv ansible + #- zypper --non-interactive --gpg-auto-import-keys update --auto-agree-with-licenses + +final_message: "TEUTHOLOGYBOOT $UPTIME" diff --git a/teuthology/deploy/openstack/userdata-ovh.yaml.orig b/teuthology/deploy/openstack/userdata-ovh.yaml.orig new file mode 100644 index 0000000000..96f838924b --- /dev/null +++ b/teuthology/deploy/openstack/userdata-ovh.yaml.orig @@ -0,0 +1,41 @@ +#cloud-config + +#chpasswd: +# list: | +# root:CHANGEME +# expire: False + +disable_root: false + +runcmd: + - [ sh, -c, echo "========= Teuthology setup started =========" ] + - | + su - -c 'cat > /tmp/ifcfg' root << EOF + BOOTPROTO=dhcp + MTU= + REMOTE_IPADDR= + STARTMODE=auto + ETHTOOL_OPTIONS= + USERCONTROL=no + EOF + + - | + su - -c 'cat > /tmp/fix-ifcfg' root << EOF + ETH=\$(ip route list | grep "scope link" | cut -f 3 -d ' ') + cp /etc/sysconfig/network/ifcfg-\$ETH /etc/sysconfig/network/ifcfg-\$ETH.backup + cp /tmp/ifcfg /etc/sysconfig/network/ifcfg-\$ETH + ifdown \$ETH + ifup \$ETH + EOF + + - bash /tmp/fix-ifcfg + - | + for i in $(seq 1 30) ; do + ping -q -c 1 8.8.8.8 && break + sleep 10 + done + - zypper -n --gpg-auto-import-keys refresh + - zypper -n --gpg-auto-import-keys install -y python python-virtualenv python-xml ansible + #- zypper -n --gpg-auto-import-keys update --auto-agree-with-licenses + +final_message: "TEUTHOLOGYBOOT $UPTIME"