launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #30187
[Merge] ~lgp171188/launchpad:charm-launchpad-scripts-bzrsyncd into launchpad:master
Guruprasad has proposed merging ~lgp171188/launchpad:charm-launchpad-scripts-bzrsyncd into launchpad:master.
Commit message:
charm: Implement the launchpad-scripts-bzrsyncd charm
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/446073
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~lgp171188/launchpad:charm-launchpad-scripts-bzrsyncd into launchpad:master.
diff --git a/charm/launchpad-scripts-bzrsyncd/README.md b/charm/launchpad-scripts-bzrsyncd/README.md
new file mode 100644
index 0000000..6e5fced
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/README.md
@@ -0,0 +1,19 @@
+# Launchpad scripts - bzrsyncd
+
+This charm sets up and runs the Launchpad bzrsyncd scripts and Celery workers.
+
+You will need the following relations:
+
+ juju relate launchpad-scripts-bzrsyncd:db postgresql:db
+ juju relate launchpad-scripts-bzrsyncd memcached
+ juju relate launchpad-scripts-bzrsyncd rabbitmq-server
+
+## Maintenance actions
+
+To stop Celery workers (perhaps in preparation for a schema upgrade), run:
+
+ juju run-action --wait launchpad-scripts-bzrsyncd/leader stop-services
+
+To start them again once maintenance is complete:
+
+ juju run-action --wait launchpad-scripts-bzrsyncd/leader start-services
diff --git a/charm/launchpad-scripts-bzrsyncd/actions.yaml b/charm/launchpad-scripts-bzrsyncd/actions.yaml
new file mode 100644
index 0000000..e99d06e
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/actions.yaml
@@ -0,0 +1,8 @@
+start-services:
+ description: Start celery workers. Usually run after maintenance.
+stop-services:
+ description: |
+ Stop celery workers. Usually run in preparation for maintenance. (Note that
+ this does not stop services in a way that will persist across a reboot. It
+ also doesn't disable cron jobs, since those are handled by the cron-control
+ mechanism instead. see lp.services.scripts.base.cronscript_enabled.)
diff --git a/charm/launchpad-scripts-bzrsyncd/actions/actions.py b/charm/launchpad-scripts-bzrsyncd/actions/actions.py
new file mode 100644
index 0000000..02617ec
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/actions/actions.py
@@ -0,0 +1,59 @@
+#! /usr/bin/python3
+# Copyright 2023 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+import subprocess
+import sys
+import traceback
+from pathlib import Path
+
+sys.path.append("lib")
+
+from charms.layer import basic # noqa: E402
+
+basic.bootstrap_charm_deps()
+basic.init_config_states()
+
+from charmhelpers.core import hookenv # noqa: E402
+
+services = (
+ "celerybeat_bzrsyncd.service",
+ "celeryd_bzrsyncd_job.service",
+ "celeryd_bzrsyncd_job_slow.service",
+)
+
+
+def start_services():
+ for service in services:
+ hookenv.log(f"Starting {service}.")
+ subprocess.run(["systemctl", "start", service], check=True)
+ hookenv.action_set({"result": "Services started"})
+
+
+def stop_services():
+ for service in services:
+ hookenv.log(f"Stopping {service}.")
+ subprocess.run(["systemctl", "stop", service], check=True)
+ hookenv.action_set({"result": "Services stopped"})
+
+
+def main(argv):
+ action = Path(argv[0]).name
+ try:
+ if action == "start-services":
+ start_services()
+ elif action == "stop-services":
+ stop_services()
+ else:
+ hookenv.action_fail(f"Action {action} not implemented.")
+ except Exception:
+ hookenv.action_fail("Unhandled exception")
+ tb = traceback.format_exc()
+ hookenv.action_set(dict(traceback=tb))
+ hookenv.log(f"Unhandled exception in action {action}:")
+ for line in tb.splitlines():
+ hookenv.log(line)
+
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/charm/launchpad-scripts-bzrsyncd/actions/start-services b/charm/launchpad-scripts-bzrsyncd/actions/start-services
new file mode 100644
index 0000000..405a394
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/actions/start-services
@@ -0,0 +1 @@
+actions.py
\ No newline at end of file
diff --git a/charm/launchpad-scripts-bzrsyncd/actions/stop-services b/charm/launchpad-scripts-bzrsyncd/actions/stop-services
new file mode 100644
index 0000000..405a394
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/actions/stop-services
@@ -0,0 +1 @@
+actions.py
\ No newline at end of file
diff --git a/charm/launchpad-scripts-bzrsyncd/charmcraft.yaml b/charm/launchpad-scripts-bzrsyncd/charmcraft.yaml
new file mode 100644
index 0000000..9b28632
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/charmcraft.yaml
@@ -0,0 +1,63 @@
+type: charm
+bases:
+ - build-on:
+ - name: ubuntu
+ channel: "20.04"
+ architectures: [amd64]
+ run-on:
+ - name: ubuntu
+ channel: "20.04"
+ architectures: [amd64]
+parts:
+ charm-wheels:
+ source: https://git.launchpad.net/~ubuntuone-hackers/ols-charm-deps/+git/wheels
+ source-commit: "42c89d9c66dbe137139b047fd54aed49b66d1a5e"
+ source-submodules: []
+ source-type: git
+ plugin: dump
+ organize:
+ "*": charm-wheels/
+ prime:
+ - "-charm-wheels"
+ ols-layers:
+ source: https://git.launchpad.net/ols-charm-deps
+ source-commit: "f63ae0386275bf9089b30c8abae252a0ea523633"
+ source-submodules: []
+ source-type: git
+ plugin: dump
+ organize:
+ "*": layers/
+ stage:
+ - layers
+ prime:
+ - "-layers"
+ launchpad-layers:
+ after:
+ - ols-layers
+ source: https://git.launchpad.net/launchpad-layers
+ source-commit: "42a4b4c4f62936b1d050c775e84f7364dfb5efc0"
+ source-submodules: []
+ source-type: git
+ plugin: dump
+ organize:
+ launchpad-base: layers/layer/launchpad-base
+ launchpad-db: layers/layer/launchpad-db
+ launchpad-payload: layers/layer/launchpad-payload
+ stage:
+ - layers
+ prime:
+ - "-layers"
+ launchpad-scripts-bzrsyncd:
+ after:
+ - charm-wheels
+ - launchpad-layers
+ source: .
+ plugin: reactive
+ build-snaps: [charm]
+ build-packages: [libpq-dev, python3-dev]
+ build-environment:
+ - CHARM_LAYERS_DIR: $CRAFT_STAGE/layers/layer
+ - CHARM_INTERFACES_DIR: $CRAFT_STAGE/layers/interface
+ - PIP_NO_INDEX: "true"
+ - PIP_FIND_LINKS: $CRAFT_STAGE/charm-wheels
+ reactive-charm-build-arguments: [--binary-wheels-from-source]
diff --git a/charm/launchpad-scripts-bzrsyncd/config.yaml b/charm/launchpad-scripts-bzrsyncd/config.yaml
new file mode 100644
index 0000000..6702f25
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/config.yaml
@@ -0,0 +1,5 @@
+options:
+ active:
+ type: boolean
+ description: Should the cron jobs and the celery services be active?
+ default: true
diff --git a/charm/launchpad-scripts-bzrsyncd/layer.yaml b/charm/launchpad-scripts-bzrsyncd/layer.yaml
new file mode 100644
index 0000000..e7b38bd
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/layer.yaml
@@ -0,0 +1,14 @@
+includes:
+ - layer:launchpad-db
+ - interface:memcache
+options:
+ ols-pg:
+ databases:
+ db:
+ name: launchpad_dev
+ roles:
+ - branchscanner
+ - merge-proposal-jobs
+ - request-daily-builds
+ - send-branch-mail
+ - translationsbranchscanner
diff --git a/charm/launchpad-scripts-bzrsyncd/metadata.yaml b/charm/launchpad-scripts-bzrsyncd/metadata.yaml
new file mode 100644
index 0000000..632b902
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/metadata.yaml
@@ -0,0 +1,20 @@
+name: launchpad-scripts-bzrsyncd
+display-name: launchpad-scripts-bzrsyncd
+summary: Launchpad scripts - bzrsyncd
+maintainer: Launchpad Developers <launchpad-dev@xxxxxxxxxxxxxxxxxxx>
+description: |
+ Launchpad is an open source suite of tools that help people and teams
+ to work together on software projects.
+
+ This charm sets up the cron jobs to run the scripts needed for 'bzrsyncd'.
+tags:
+ # https://juju.is/docs/charm-metadata#heading--charm-store-fields
+ - network
+series:
+ - focal
+subordinate: false
+requires:
+ session-db:
+ interface: pgsql
+ memcache:
+ interface: memcache
diff --git a/charm/launchpad-scripts-bzrsyncd/reactive/launchpad-scripts-bzrsyncd.py b/charm/launchpad-scripts-bzrsyncd/reactive/launchpad-scripts-bzrsyncd.py
new file mode 100644
index 0000000..6e85f10
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/reactive/launchpad-scripts-bzrsyncd.py
@@ -0,0 +1,104 @@
+# Copyright 2023 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+import subprocess
+
+from charmhelpers.core import hookenv, host, templating
+from charms.launchpad.base import configure_email, get_service_config
+from charms.launchpad.payload import configure_cron, configure_lazr
+from charms.reactive import (
+ endpoint_from_flag,
+ remove_state,
+ set_state,
+ when,
+ when_not,
+ when_not_all,
+)
+
+
+def configure_logrotate(config):
+ hookenv.log("Writing logrotate configuration.")
+ templating.render(
+ "logrotate.conf.j2",
+ "/etc/logrotate.d/launchpad",
+ config,
+ perms=0o644,
+ )
+
+
+@host.restart_on_change(
+ {
+ "/lib/systemd/system/celerybeat-bzrsyncd.service": [
+ "celerybeat-bzrsyncd",
+ ],
+ "/lib/systemd/system/celeryd_bzrsyncd_job.service": [
+ "celeryd_bzrsyncd_job",
+ ],
+ "/lib/systemd/system/celeryd_bzrsyncd_job_slow.service": [
+ "celeryd_bzrsyncd_job_slow",
+ ]
+ }
+)
+def configure_celery(config):
+ hookenv.log("Writing celery systemd service files.")
+ destination_dir = "/lib/systemd/system"
+ service_files = (
+ "celerybeat_bzrsyncd.service",
+ "celeryd_bzrsyncd_job.service",
+ "celeryd_bzrsyncd_job_slow.service",
+ )
+ for service_file in service_files:
+ templating.render(
+ f"{service_file}.j2",
+ f"{destination_dir}/{service_file}",
+ config,
+ )
+ subprocess.check_call(["systemctl", "daemon-reload"])
+ for service_file in service_files:
+ subprocess.check_call(["systemctl", "enable", service_file])
+
+
+@when(
+ "launchpad.db.configured",
+ "memcache.available",
+)
+@when_not("service.configured")
+def configure():
+ config = get_service_config()
+ memcache = endpoint_from_flag("memcache.available")
+ config["memcache_servers"] = ",".join(
+ sorted(
+ f"({host}:{port},1)"
+ for host, port in memcache.memcache_hosts_ports()
+ )
+ )
+ configure_lazr(
+ config,
+ "launchpad-scripts-bzrsyncd-lazr.conf.j2",
+ "launchpad-scripts-bzrsyncd/launchpad-lazr.conf",
+ )
+ configure_lazr(
+ config,
+ "launchpad-scripts-bzrsyncd-secrets-lazr.conf.j2",
+ "launchpad-scripts-bzrsyncd-secrets-lazr.conf",
+ secret=True,
+ )
+ configure_email(config, "launchpad-scripts")
+ configure_logrotate(config)
+ set_state("service.configured")
+ configure_cron(config, "crontab.j2")
+ configure_celery(config)
+
+
+@when("service.configured")
+def check_is_running():
+ hookenv.status_set("active", "Ready")
+
+
+@when("service.configured")
+@when_not_all(
+ "launchpad.db.configured",
+ "memcache.available",
+)
+def deconfigure():
+ remove_state("service.configured")
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/celerybeat_bzrsyncd.service.j2 b/charm/launchpad-scripts-bzrsyncd/templates/celerybeat_bzrsyncd.service.j2
new file mode 100644
index 0000000..598aecc
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/celerybeat_bzrsyncd.service.j2
@@ -0,0 +1,15 @@
+[Unit]
+Description=celerybeat scheduler for bzrsyncd
+After=syslog.target network.target remote-fs.target nss-lookup.target
+
+[Service]
+Environment=LPCONFIG=launchpad-scripts-bzrsyncd
+User=launchpad
+WorkingDirectory={{ code_dir }}
+ExecStart={{ code_dir }}/bin/celery beat --config=lp.services.job.celeryconfig
+Restart=on-failure
+LimitNOFILE=10000
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job.service.j2 b/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job.service.j2
new file mode 100644
index 0000000..47d6eda
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job.service.j2
@@ -0,0 +1,24 @@
+[Unit]
+Description=Celery service for Launchpad bzrsyncd jobs
+After=network.target
+
+[Service]
+Type=exec
+User=launchpad
+Group=launchpad
+Environment=LPCONFIG=launchpad-scripts-bzrsyncd
+WorkingDirectory={{ code_dir }}
+ExecStart={{ code_dir }}/bin/celery worker \
+ --queue bzrsyncd_job \
+ --config=lp.services.job.celeryconfig \
+ --hostname=launchpad_bzrsyncd_job \
+ --loglevel=DEBUG \
+ --logfile={{ logs_dir }}/celeryd_launchpad_bzrsyncd_job.log
+ExecStop=/bin/kill -TERM $MAINPID
+ExecReload=/bin/kill -HUP $MAINPID
+PrivateTmp=true
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job_slow.service.j2 b/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job_slow.service.j2
new file mode 100644
index 0000000..34923be
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/celeryd_bzrsyncd_job_slow.service.j2
@@ -0,0 +1,24 @@
+[Unit]
+Description=Celery service for Launchpad bzrsyncd slow jobs
+After=network.target
+
+[Service]
+Type=exec
+User=launchpad
+Group=launchpad
+Environment=LPCONFIG=launchpad-scripts-bzrsyncd
+WorkingDirectory={{ code_dir }}
+ExecStart={{ code_dir }}/bin/celery worker \
+ --queue bzrsyncd_job_slow \
+ --config=lp.services.job.celeryconfig \
+ --hostname=launchpad_bzrsyncd_job_slow \
+ --loglevel=DEBUG \
+ --logfile={{ logs_dir }}/celeryd_launchpad_bzrsyncd_job_slow.log
+ExecStop=/bin/kill -TERM $MAINPID
+ExecReload=/bin/kill -HUP $MAINPID
+PrivateTmp=true
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/crontab.j2 b/charm/launchpad-scripts-bzrsyncd/templates/crontab.j2
new file mode 100644
index 0000000..923857d
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/crontab.j2
@@ -0,0 +1,32 @@
+TZ=UTC
+MAILTO={{ cron_mailto }}
+LPCONFIG=launchpad-scripts-bzrsyncd
+
+{%- if active %}
+
+# cleanup /tmp/bzr-limbo-* leftovers
+0 1 * * * find /tmp -maxdepth 1 -name 'bzr-limbo-??????' -type d -mtime +1|xargs -r -I@ rm -rf '@'
+
+# branch scanner
+* * * * * {{ code_dir }}/cronscripts/process-job-source.py IBranchScanJobSource -q --log-file=DEBUG:{{ logs_dir }}/process-job-source.IBranchScanJobSource.log
+
+# Branch Updates - emailed out
+# set hard memory limit as per https://bugs.launchpad.net/launchpad/+bug/585126
+* * * * * ulimit -v 1843200; {{ code_dir }}/cronscripts/process-job-source.py IRevisionMailJobSource -q --log-file=DEBUG:{{ logs_dir }}/process-job-source.IRevisionMailJobSource.log
+* * * * * ulimit -v 1843200; {{ code_dir}}/cronscripts/process-job-source.py IRevisionsAddedJobSource -q --log-file=DEBUG:{{ logs_dir }}/process-job-source.IRevisionsAddedJobSource.log
+
+# processes code branches that have new translations imports pending
+*/10 * * * * {{ code_dir }}/cronscripts/process-job-source.py IRosettaUploadJobSource -q --log-file=DEBUG:{{ logs_dir }}/process-job-source.IRosettaUploadJobSource.log
+
+# Update or create previews diffs for branch merge proposals &
+# Send email about new merge proposals, generating a diff first if needed
+* * * * * {{ code_dir }}/cronscripts/process-job-source.py IBranchMergeProposalJobSource -q --log-file=DEBUG:{{ logs_dir }}/process-job-source.IBranchMergeProposalJobSource.log
+
+# Script requests builds for source package recipes that have "build daily" enabled
+*/15 * * * * {{ code_dir }}/cronscripts/request_daily_builds.py -v >> {{ logs_dir }}/request_daily_builds.log 2>&1
+
+{%- endif %}
+
+# OOPS amqp
+*/15 * * * * {{ code_dir }}/bin/datedir2amqp --exchange oopses --host {{ rabbitmq_host }} --username {{ rabbitmq_username }} --password {{ rabbitmq_password }} --vhost {{ rabbitmq_vhost }} --repo {{ oopses_dir }} --key ""
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-lazr.conf.j2 b/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-lazr.conf.j2
new file mode 100644
index 0000000..955c9df
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-lazr.conf.j2
@@ -0,0 +1,19 @@
+# Public configuration data. The contents of this file may be freely shared
+# with developers if needed for debugging.
+
+# A schema's sections, keys, and values are automatically inherited, except
+# for '.optional' sections. Update this config to override key values.
+# Values are strings, except for numbers that look like ints. The tokens
+# true, false, and none are treated as True, False, and None.
+
+{% from "macros.j2" import opt -%}
+
+[meta]
+extends: ../launchpad-db-lazr.conf
+
+[codehosting]
+internal_branch_by_id_root: http://bazaar.lp.internal/
+
+[memcache]
+servers: {{ memcache_servers }}
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-secrets-lazr.conf.j2 b/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-secrets-lazr.conf.j2
new file mode 100644
index 0000000..e7d11ab
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/launchpad-scripts-bzrsyncd-secrets-lazr.conf.j2
@@ -0,0 +1,10 @@
+# Secret configuration data. This is stored in an overlay directory, mainly
+# to avoid accidental information leaks from the public configuration file.
+# Entries in this file should not be shared with developers, although the
+# structure of the file is not secret, only configuration values.
+
+# A schema's sections, keys, and values are automatically inherited, except
+# for '.optional' sections. Update this config to override key values.
+# Values are strings, except for numbers that look like ints. The tokens
+# true, false, and none are treated as True, False, and None.
+
diff --git a/charm/launchpad-scripts-bzrsyncd/templates/logrotate.conf.j2 b/charm/launchpad-scripts-bzrsyncd/templates/logrotate.conf.j2
new file mode 100644
index 0000000..fc28d9d
--- /dev/null
+++ b/charm/launchpad-scripts-bzrsyncd/templates/logrotate.conf.j2
@@ -0,0 +1,13 @@
+{{ logs_dir }}/*.log {
+ rotate 21
+ dateext
+ daily
+ compress
+ delaycompress
+ sharedscripts
+ postrotate
+ systemctl restart celeryd_bzrsyncd_job
+ systemctl restart celeryd_bzrsyncd_job_slow
+ endscript
+}
+
Follow ups