ClickHouse/tests/jepsen.clickhouse/src/jepsen/clickhouse/utils.clj

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

203 lines
6.6 KiB
Clojure
Raw Normal View History

2022-10-24 11:24:33 +00:00
(ns jepsen.clickhouse.utils
(:require [jepsen.control.util :as cu]
[jepsen
[control :as c]
[db :as db]]
[jepsen.clickhouse.constants :refer :all]
[clojure.tools.logging :refer :all]
[clojure.java.io :as io])
(:import (java.security MessageDigest)))
(defn exec-with-retries
[retries f & args]
(let [res (try {:value (apply f args)}
(catch Exception e
(if (zero? retries)
(throw e)
{:exception e})))]
(if (:exception res)
(do (Thread/sleep 1000) (recur (dec retries) f args))
(:value res))))
(defn parse-long
"Parses a string to a Long. Passes through `nil` and empty strings."
[s]
(if (and s (> (count s) 0))
(Long/parseLong s)))
2022-10-28 11:05:56 +00:00
(defn cart [colls]
(if (empty? colls)
'(())
(for [more (cart (rest colls))
x (first colls)]
(cons x more))))
2022-10-24 11:24:33 +00:00
(defn md5 [^String s]
(let [algorithm (MessageDigest/getInstance "MD5")
raw (.digest algorithm (.getBytes s))]
(format "%032x" (BigInteger. 1 raw))))
(defn non-precise-cached-wget!
[url]
(let [encoded-url (md5 url)
expected-file-name (.getName (io/file url))
dest-folder (str binaries-cache-dir "/" encoded-url)
2022-11-04 13:04:29 +00:00
dest-file (str dest-folder "/clickhouse")
2022-10-24 11:24:33 +00:00
dest-symlink (str root-folder "/" expected-file-name)
wget-opts (concat cu/std-wget-opts [:-O dest-file])]
(when-not (cu/exists? dest-file)
(info "Downloading" url)
(do (c/exec :mkdir :-p dest-folder)
(c/cd dest-folder
(cu/wget-helper! wget-opts url))))
(c/exec :rm :-rf dest-symlink)
(c/exec :ln :-s dest-file dest-symlink)
dest-symlink))
(defn get-clickhouse-url
[url]
2022-11-04 13:04:29 +00:00
(non-precise-cached-wget! url))
2022-10-24 11:24:33 +00:00
(defn get-clickhouse-scp
[path]
(c/upload path (str root-folder "/clickhouse")))
(defn download-clickhouse
[source]
(info "Downloading clickhouse from" source)
(cond
2022-11-04 13:04:29 +00:00
(clojure.string/starts-with? source "http") (get-clickhouse-url source)
2022-10-24 11:24:33 +00:00
(.exists (io/file source)) (get-clickhouse-scp source root-folder)
:else (throw (Exception. (str "Don't know how to download clickhouse from" source)))))
(defn unpack-deb
[path]
(do
(c/exec :dpkg :-x path root-folder)
(c/exec :rm :-f path)
(c/exec :mv (str root-folder "/usr/bin/clickhouse") root-folder)
(c/exec :rm :-rf (str root-folder "/usr") (str root-folder "/etc"))))
(defn unpack-tgz
[path]
(do
(c/exec :mkdir :-p (str root-folder "/unpacked"))
2023-01-09 06:01:20 +00:00
(c/exec :tar :-xvf path :-C (str root-folder "/unpacked"))
2022-10-24 11:24:33 +00:00
(c/exec :rm :-f path)
(let [subdir (c/exec :ls (str root-folder "/unpacked"))]
(c/exec :mv (str root-folder "/unpacked/" subdir "/usr/bin/clickhouse") root-folder)
(c/exec :rm :-fr (str root-folder "/unpacked")))))
(defn chmod-binary
[path]
(info "Binary path chmod" path)
(c/exec :chmod :+x path))
(defn install-downloaded-clickhouse
[path]
(cond
(clojure.string/ends-with? path ".deb") (unpack-deb path root-folder)
(clojure.string/ends-with? path ".tgz") (unpack-tgz path root-folder)
(clojure.string/ends-with? path "clickhouse") (chmod-binary path)
:else (throw (Exception. (str "Don't know how to install clickhouse from path" path)))))
(defn collect-traces
[test node]
(let [pid (c/exec :pidof "clickhouse")]
(c/exec :timeout :-s "KILL" "60" :gdb :-ex "set pagination off" :-ex (str "set logging file " logs-dir "/gdb.log") :-ex
"set logging on" :-ex "backtrace" :-ex "thread apply all backtrace"
:-ex "backtrace" :-ex "detach" :-ex "quit" :--pid pid :|| :true)))
(defn wait-clickhouse-alive!
[node test clickhouse-alive? & {:keys [maxtries] :or {maxtries 30}}]
(loop [i 0]
(cond (> i maxtries) false
(clickhouse-alive? node test) true
:else (do (Thread/sleep 1000) (recur (inc i))))))
(defn kill-clickhouse!
[node test]
(info "Killing server on node" node)
(c/su
(cu/stop-daemon! binary-path pid-file-path)
(c/exec :rm :-fr (str data-dir "/status"))))
(defn start-clickhouse!
[node test clickhouse-alive? & binary-args]
(info "Starting server on node" node)
(c/su
(cu/start-daemon!
{:pidfile pid-file-path
:logfile stderr-file
:chdir data-dir}
binary-path
binary-args)
2022-11-07 08:49:26 +00:00
(info "Waiting for server")
2022-10-24 11:24:33 +00:00
(wait-clickhouse-alive! node test clickhouse-alive?)))
(defn prepare-dirs
[]
(do
(c/exec :mkdir :-p root-folder)
(c/exec :mkdir :-p data-dir)
(c/exec :mkdir :-p coordination-data-dir)
(c/exec :mkdir :-p logs-dir)
(c/exec :mkdir :-p configs-dir)
(c/exec :mkdir :-p sub-configs-dir)
(c/exec :touch stderr-file)
(c/exec :chown :-R :root root-folder)))
(defn db
[version reuse-binary start-clickhouse! extra-setup]
(reify db/DB
(setup! [_ test node]
(c/su
(do
(info "Preparing directories")
(prepare-dirs)
(if (or (not (cu/exists? binary-path)) (not reuse-binary))
(do (info "Downloading clickhouse")
2022-11-04 13:04:29 +00:00
(let [clickhouse-path (download-clickhouse version)]
2022-10-24 11:24:33 +00:00
(install-downloaded-clickhouse clickhouse-path)))
(info "Binary already exsist on path" binary-path "skipping download"))
(extra-setup test node)
(info "Starting server")
(start-clickhouse! node test)
(info "ClickHouse started"))))
(teardown! [_ test node]
(info node "Tearing down clickhouse")
(c/su
(kill-clickhouse! node test)
(if (not reuse-binary)
(c/exec :rm :-rf binary-path))
(c/exec :rm :-rf pid-file-path)
(c/exec :rm :-rf data-dir)
(c/exec :rm :-rf logs-dir)
(c/exec :rm :-rf configs-dir)))
db/LogFiles
(log-files [_ test node]
(c/su
;(if (cu/exists? pid-file-path)
;(do
; (info node "Collecting traces")
; (collect-traces test node logs-dir))
;(info node "Pid files doesn't exists"))
(kill-clickhouse! node test)
(if (cu/exists? coordination-data-dir)
(do
(info node "Coordination files exists, going to compress")
(c/cd data-dir
(c/exec :tar :czf "coordination.tar.gz" "coordination"))))
(if (cu/exists? (str logs-dir))
(do
(info node "Logs exist, going to compress")
(c/cd root-folder
(c/exec :tar :czf "logs.tar.gz" "logs"))) (info node "Logs are missing")))
(let [common-logs [(str root-folder "/logs.tar.gz") (str data-dir "/coordination.tar.gz")]
gdb-log (str logs-dir "/gdb.log")]
(if (cu/exists? (str logs-dir "/gdb.log"))
(conj common-logs gdb-log)
common-logs)))))