← Back to team overview

launchpad-reviewers team mailing list archive

[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