From 4239f110b8a7b5d8f595d2ff12d967cc9191e9cc Mon Sep 17 00:00:00 2001 From: Teddy Astie Date: Mon, 2 Oct 2023 14:47:50 +0200 Subject: [PATCH] WIP Introduce xcp-metrics-plugin-xen plugin for xcp-rrdd xcp-metrics-plugin-xen is meant as a replacement for - the metrics collection built into xcp-rrdd, which requires the latter to depend on libxenctrl - the rrdp-pm plugin, which also fetches data through libxenctrl Metrics are collected using the Rust crate, structured in a suitable way for upcoming OpenMetrics support, and communicated to xcp-rrdd using its v2 protocol. NOTE: at the time of this writing, we still rely on extra features we had to add to the crate, PR pending. Signed-off-by: Teddy Astie Reviewed-by: Yann Dirson --- .github/workflows/rust.yml | 79 + .gitignore | 2 + Cargo.lock | 2100 +++++++++++++++++ Cargo.toml | 12 + LICENSE | 613 +++++ devscripts/gen-vendor-tarball.sh | 21 + metrics_sample/xcp-rrdd-mem_host | Bin 0 -> 4096 bytes metrics_sample/xcp-rrdd-xenpm | Bin 0 -> 32768 bytes plugins/xcp-metrics-plugin-common/Cargo.toml | 34 + .../src/bridge/mod.rs | 3 + .../src/bridge/v3_to_v2.rs | 142 ++ plugins/xcp-metrics-plugin-common/src/lib.rs | 7 + .../xcp-metrics-plugin-common/src/plugin.rs | 143 ++ .../src/protocol_v2.rs | 170 ++ .../src/protocol_v3/mod.rs | 116 + .../src/protocol_v3/utils.rs | 72 + .../src/xenstore/mock.rs | 219 ++ .../src/xenstore/mod.rs | 11 + .../src/xenstore/read.rs | 18 + .../src/xenstore/watch.rs | 81 + .../src/xenstore/watch_cache.rs | 111 + .../src/xenstore/write.rs | 20 + plugins/xcp-metrics-plugin-xen/Cargo.toml | 26 + plugins/xcp-metrics-plugin-xen/src/main.rs | 106 + .../src/metrics/domain.rs | 134 ++ .../src/metrics/host.rs | 36 + .../xcp-metrics-plugin-xen/src/metrics/mod.rs | 132 ++ .../src/metrics/physical.rs | 204 ++ .../xcp-metrics-plugin-xen/src/metrics/pm.rs | 113 + xapi-rs/Cargo.toml | 59 + xapi-rs/README.md | 7 + xapi-rs/src/lib.rs | 90 + xapi-rs/src/rpc/message.rs | 396 ++++ xapi-rs/src/rpc/methods.rs | 63 + xapi-rs/src/rpc/mod.rs | 109 + xapi-rs/src/rpc/response.rs | 9 + xapi-rs/src/rpc/test.rs | 67 + xapi-rs/src/rpc/xml.rs | 24 + xapi-rs/src/utils/mod.rs | 2 + xapi-rs/src/utils/write_bridge.rs | 11 + xcp-metrics-common/Cargo.toml | 45 + xcp-metrics-common/README.md | 21 + xcp-metrics-common/build.rs | 3 + xcp-metrics-common/src/lib.rs | 9 + xcp-metrics-common/src/metrics.rs | 140 ++ xcp-metrics-common/src/openmetrics/convert.rs | 462 ++++ xcp-metrics-common/src/openmetrics/mod.rs | 9 + xcp-metrics-common/src/openmetrics/test.rs | 169 ++ xcp-metrics-common/src/openmetrics/text.rs | 261 ++ .../src/openmetrics_data_model.proto | 214 ++ xcp-metrics-common/src/protocol_v3.rs | 236 ++ xcp-metrics-common/src/rrdd/mod.rs | 8 + .../src/rrdd/protocol_common.rs | 381 +++ xcp-metrics-common/src/rrdd/protocol_v2.rs | 328 +++ xcp-metrics-common/src/rrdd/rrd_updates.rs | 162 ++ xcp-metrics-common/src/rrdd/test.rs | 108 + xcp-metrics-common/src/test.rs | 250 ++ xcp-metrics-common/src/utils/delta.rs | 253 ++ xcp-metrics-common/src/utils/mapping.rs | 173 ++ xcp-metrics-common/src/utils/mod.rs | 6 + xcp-metrics-common/src/utils/write_bridge.rs | 11 + 61 files changed, 8811 insertions(+) create mode 100644 .github/workflows/rust.yml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100755 devscripts/gen-vendor-tarball.sh create mode 100644 metrics_sample/xcp-rrdd-mem_host create mode 100644 metrics_sample/xcp-rrdd-xenpm create mode 100644 plugins/xcp-metrics-plugin-common/Cargo.toml create mode 100644 plugins/xcp-metrics-plugin-common/src/bridge/mod.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/bridge/v3_to_v2.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/lib.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/plugin.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/protocol_v2.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/protocol_v3/mod.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/protocol_v3/utils.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/mock.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/mod.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/read.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/watch.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/watch_cache.rs create mode 100644 plugins/xcp-metrics-plugin-common/src/xenstore/write.rs create mode 100644 plugins/xcp-metrics-plugin-xen/Cargo.toml create mode 100644 plugins/xcp-metrics-plugin-xen/src/main.rs create mode 100644 plugins/xcp-metrics-plugin-xen/src/metrics/domain.rs create mode 100644 plugins/xcp-metrics-plugin-xen/src/metrics/host.rs create mode 100644 plugins/xcp-metrics-plugin-xen/src/metrics/mod.rs create mode 100644 plugins/xcp-metrics-plugin-xen/src/metrics/physical.rs create mode 100644 plugins/xcp-metrics-plugin-xen/src/metrics/pm.rs create mode 100644 xapi-rs/Cargo.toml create mode 100644 xapi-rs/README.md create mode 100644 xapi-rs/src/lib.rs create mode 100644 xapi-rs/src/rpc/message.rs create mode 100644 xapi-rs/src/rpc/methods.rs create mode 100644 xapi-rs/src/rpc/mod.rs create mode 100644 xapi-rs/src/rpc/response.rs create mode 100644 xapi-rs/src/rpc/test.rs create mode 100644 xapi-rs/src/rpc/xml.rs create mode 100644 xapi-rs/src/utils/mod.rs create mode 100644 xapi-rs/src/utils/write_bridge.rs create mode 100644 xcp-metrics-common/Cargo.toml create mode 100644 xcp-metrics-common/README.md create mode 100644 xcp-metrics-common/build.rs create mode 100644 xcp-metrics-common/src/lib.rs create mode 100644 xcp-metrics-common/src/metrics.rs create mode 100644 xcp-metrics-common/src/openmetrics/convert.rs create mode 100644 xcp-metrics-common/src/openmetrics/mod.rs create mode 100644 xcp-metrics-common/src/openmetrics/test.rs create mode 100644 xcp-metrics-common/src/openmetrics/text.rs create mode 100644 xcp-metrics-common/src/openmetrics_data_model.proto create mode 100644 xcp-metrics-common/src/protocol_v3.rs create mode 100644 xcp-metrics-common/src/rrdd/mod.rs create mode 100644 xcp-metrics-common/src/rrdd/protocol_common.rs create mode 100644 xcp-metrics-common/src/rrdd/protocol_v2.rs create mode 100644 xcp-metrics-common/src/rrdd/rrd_updates.rs create mode 100644 xcp-metrics-common/src/rrdd/test.rs create mode 100644 xcp-metrics-common/src/test.rs create mode 100644 xcp-metrics-common/src/utils/delta.rs create mode 100644 xcp-metrics-common/src/utils/mapping.rs create mode 100644 xcp-metrics-common/src/utils/mod.rs create mode 100644 xcp-metrics-common/src/utils/write_bridge.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..4bba49d --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,79 @@ +name: Rust + +on: + push: + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + #container: + # image: centos8 + + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: 1.70.0 + override: true + - name: Installing dependency packages + run: sudo apt update && sudo apt install -y libxen-dev protobuf-compiler + + - name: Build + run: cargo build --verbose + + doc: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: 1.70.0 + override: true + - name: Installing dependency packages + run: sudo apt update && sudo apt install -y libxen-dev protobuf-compiler + + - name: Build docs + run: cargo doc --workspace --no-deps + + - name: Upload docs + uses: actions/upload-artifact@v3 + with: + name: rustdoc-html + path: ./target/doc + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + - name: Installing dependency packages + run: sudo apt update && sudo apt install -y libxen-dev protobuf-compiler + + - name: Run tests + run: | + cargo clean + cargo test --verbose + env: + CARGO_INCREMENTAL: '0' + RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests' + + - name: Install grcov + run: cargo install grcov + - name: Test coverage report + run: grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existing -o ./target/debug/coverage/ + + - name: Upload test coverage report + uses: actions/upload-artifact@v3 + with: + name: coverage-html + path: ./target/debug/coverage/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0034a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/third-party/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3af5ca2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2100 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon 1.0.2", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstream" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "735917dc4838cee6a072ea1fd4b6e4e6ff00cbe95c7875967482961c36a0b68f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon 2.1.0", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + +[[package]] +name = "bindgen" +version = "0.49.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c07087f3d5731bf3fb375a81841b99597e25dc11bd3bc72d16d43adf6624a6e" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "cfg-if 0.1.10", + "clang-sys", + "clap 2.34.0", + "env_logger 0.6.2", + "fxhash", + "lazy_static", + "log", + "peeking_take_while", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "shlex", + "which 2.0.1", +] + +[[package]] +name = "bindgen" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "cfg-if 0.1.10", + "clang-sys", + "clap 2.34.0", + "env_logger 0.7.1", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2 1.0.67", + "quote 1.0.33", + "regex", + "rustc-hash", + "shlex", + "which 3.1.1", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "clang-sys" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" +dependencies = [ + "glob", + "libc", + "libloading 0.5.2", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "4.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e" +dependencies = [ + "anstream 0.3.2", + "anstyle", + "clap_lex", + "strsim 0.10.0", +] + +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.1", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dxr" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb82be7ae6f2d3234d610137f467d28180220650d12cfebbf55b5fc650d651a5" +dependencies = [ + "base64", + "chrono", + "dxr_derive", + "quick-xml", + "serde", + "thiserror", +] + +[[package]] +name = "dxr_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceb12dbd2a70e5e0aaf6e443a912926c3b64e3a0d7414513fb1be0d2129fa919" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "enum-primitive-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd" +dependencies = [ + "num-traits 0.1.43", + "quote 0.3.15", + "syn 0.11.11", +] + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check 0.9.4", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyperlocal" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +dependencies = [ + "futures-util", + "hex", + "hyper", + "pin-project", + "tokio", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.1", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.3", + "rustix", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "jsonrpc-base" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "118f2000680cf8cdd1bb102eb80a8069f26a7f99ac92b10d3101d96b4e4b3b16" +dependencies = [ + "serde", + "serde_json", + "uuid", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check 0.1.5", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.3", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pest" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "pest_meta" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.0.2", +] + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2 1.0.67", + "syn 1.0.109", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which 4.4.2", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2 1.0.67", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "unicode-ident", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.4", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.2", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if 1.0.0", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", + "rand", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +dependencies = [ + "failure", + "libc", +] + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] + +[[package]] +name = "xapi" +version = "0.1.0" +dependencies = [ + "anstream 0.4.0", + "anyhow", + "clap_builder", + "clap_lex", + "crc32fast", + "dxr", + "hyper", + "hyperlocal", + "indexmap 2.0.2", + "json5", + "jsonrpc-base", + "maplit", + "prost", + "prost-types", + "quick-xml", + "serde", + "serde_json", + "tokio", + "uuid", +] + +[[package]] +name = "xcp-metrics-common" +version = "0.1.0" +dependencies = [ + "anyhow", + "crc32fast", + "indexmap 2.0.2", + "json5", + "maplit", + "prost", + "prost-build", + "prost-types", + "serde", + "serde_json", + "tokio", + "uuid", + "xcp-metrics-common", +] + +[[package]] +name = "xcp-metrics-plugin-common" +version = "0.1.0" +dependencies = [ + "anyhow", + "dashmap", + "futures", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", + "xapi", + "xcp-metrics-common", + "xenstore-rs", +] + +[[package]] +name = "xcp-metrics-plugin-xen" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap 4.3.24", + "maplit", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", + "xcp-metrics-common", + "xcp-metrics-plugin-common", + "xenctrl", + "xenctrl-sys", +] + +[[package]] +name = "xenctrl" +version = "0.4.9" +source = "git+https://github.com/TSnake41/xenctrl?branch=more_functions#67fe0a4cb24827120e40b1b9a5810642e56bbc90" +dependencies = [ + "enum-primitive-derive", + "libloading 0.7.4", + "log", + "num-traits 0.2.16", + "xenctrl-sys", + "xenvmevent-sys", +] + +[[package]] +name = "xenctrl-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87db734ac7b5728685bb649a7920a8072528519668f637bfe4408b8bc53a0eff" +dependencies = [ + "bindgen 0.49.4", +] + +[[package]] +name = "xenstore-rs" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5a43f0523ad3bafe61422f023f050302618e3860c7c94a3b1695bd37899422" +dependencies = [ + "enum-primitive-derive", + "libc", + "libloading 0.7.4", + "log", + "num-traits 0.2.16", + "xenstore-sys", +] + +[[package]] +name = "xenstore-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8bea9e3a7459845435311b571fb7891460e50903a34bd7ccbe26e25a898dc1" +dependencies = [ + "bindgen 0.49.4", +] + +[[package]] +name = "xenvmevent-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83bfefa952f597dd3961d9bc02e67c4d25a32aff25768282eac9b0624115f626" +dependencies = [ + "bindgen 0.52.0", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8243fbe --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[workspace] +package.version = "0.1.0" +package.repository = "https://github.com/xcp-ng/xcp-metrics" +package.categories = ["virtualization"] +members = [ + "xcp-metrics-common", + "xapi-rs", + "plugins/xcp-metrics-plugin-common", + "plugins/xcp-metrics-plugin-xen", +] +[profile.release] +lto = true \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e37e32e --- /dev/null +++ b/LICENSE @@ -0,0 +1,613 @@ +GNU AFFERO GENERAL PUBLIC LICENSE + +Version 3, 19 November 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The GNU Affero General Public License is a free, copyleft license for software +and other kinds of works, specifically designed to ensure cooperation with +the community in the case of network server software. + +The licenses for most software and other practical works are designed to take +away your freedom to share and change the works. By contrast, our General +Public Licenses are intended to guarantee your freedom to share and change +all versions of a program--to make sure it remains free software for all its +users. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom +to distribute copies of free software (and charge for them if you wish), that +you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs, and that you know you +can do these things. + +Developers that use our General Public Licenses protect your rights with two +steps: (1) assert copyright on the software, and (2) offer you this License +which gives you legal permission to copy, distribute and/or modify the software. + +A secondary benefit of defending all users' freedom is that improvements made +in alternate versions of the program, if they receive widespread use, become +available for other developers to incorporate. Many developers of free software +are heartened and encouraged by the resulting cooperation. However, in the +case of software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and letting +the public access it on a server without ever releasing its source code to +the public. + +The GNU Affero General Public License is designed specifically to ensure that, +in such cases, the modified source code becomes available to the community. +It requires the operator of a network server to provide the source code of +the modified version running there to the users of that server. Therefore, +public use of a modified version, on a publicly accessible server, gives the +public access to the source code of the modified version. + +An older license, called the Affero General Public License and published by +Affero, was designed to accomplish similar goals. This is a different license, +not a version of the Affero GPL, but Affero has released a new version of +the Affero GPL which permits relicensing under this license. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of works, +such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this License. +Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals +or organizations. + +To "modify" a work means to copy from or adapt all or part of the work in +a fashion requiring copyright permission, other than the making of an exact +copy. The resulting work is called a "modified version" of the earlier work +or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based on the +Program. + +To "propagate" a work means to do anything with it that, without permission, +would make you directly or secondarily liable for infringement under applicable +copyright law, except executing it on a computer or modifying a private copy. +Propagation includes copying, distribution (with or without modification), +making available to the public, and in some countries other activities as +well. + +To "convey" a work means any kind of propagation that enables other parties +to make or receive copies. Mere interaction with a user through a computer +network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" to the +extent that it includes a convenient and prominently visible feature that +(1) displays an appropriate copyright notice, and (2) tells the user that +there is no warranty for the work (except to the extent that warranties are +provided), that licensees may convey the work under this License, and how +to view a copy of this License. If the interface presents a list of user commands +or options, such as a menu, a prominent item in the list meets this criterion. + + 1. Source Code. + +The "source code" for a work means the preferred form of the work for making +modifications to it. "Object code" means any non-source form of a work. + +A "Standard Interface" means an interface that either is an official standard +defined by a recognized standards body, or, in the case of interfaces specified +for a particular programming language, one that is widely used among developers +working in that language. + +The "System Libraries" of an executable work include anything, other than +the work as a whole, that (a) is included in the normal form of packaging +a Major Component, but which is not part of that Major Component, and (b) +serves only to enable use of the work with that Major Component, or to implement +a Standard Interface for which an implementation is available to the public +in source code form. A "Major Component", in this context, means a major essential +component (kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to produce +the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all the source +code needed to generate, install, and (for an executable work) run the object +code and to modify the work, including scripts to control those activities. +However, it does not include the work's System Libraries, or general-purpose +tools or generally available free programs which are used unmodified in performing +those activities but which are not part of the work. For example, Corresponding +Source includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically linked +subprograms that the work is specifically designed to require, such as by +intimate data communication or control flow between those + + subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate +automatically from other parts of the Corresponding Source. + + The Corresponding Source for a work in source code form is that same work. + + 2. Basic Permissions. + +All rights granted under this License are granted for the term of copyright +on the Program, and are irrevocable provided the stated conditions are met. +This License explicitly affirms your unlimited permission to run the unmodified +Program. The output from running a covered work is covered by this License +only if the output, given its content, constitutes a covered work. This License +acknowledges your rights of fair use or other equivalent, as provided by copyright +law. + +You may make, run and propagate covered works that you do not convey, without +conditions so long as your license otherwise remains in force. You may convey +covered works to others for the sole purpose of having them make modifications +exclusively for you, or provide you with facilities for running those works, +provided that you comply with the terms of this License in conveying all material +for which you do not control copyright. Those thus making or running the covered +works for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of your copyrighted +material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions +stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological measure +under any applicable law fulfilling obligations under article 11 of the WIPO +copyright treaty adopted on 20 December 1996, or similar laws prohibiting +or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention +of technological measures to the extent such circumvention is effected by +exercising rights under this License with respect to the covered work, and +you disclaim any intention to limit operation or modification of the work +as a means of enforcing, against the work's users, your or third parties' +legal rights to forbid circumvention of technological measures. + + 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you receive +it, in any medium, provided that you conspicuously and appropriately publish +on each copy an appropriate copyright notice; keep intact all notices stating +that this License and any non-permissive terms added in accord with section +7 apply to the code; keep intact all notices of the absence of any warranty; +and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you +may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to produce +it from the Program, in the form of source code under the terms of section +4, provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified it, and +giving a relevant date. + +b) The work must carry prominent notices stating that it is released under +this License and any conditions added under section 7. This requirement modifies +the requirement in section 4 to "keep intact all notices". + +c) You must license the entire work, as a whole, under this License to anyone +who comes into possession of a copy. This License will therefore apply, along +with any applicable section 7 additional terms, to the whole of the work, +and all its parts, regardless of how they are packaged. This License gives +no permission to license the work in any other way, but it does not invalidate +such permission if you have separately received it. + +d) If the work has interactive user interfaces, each must display Appropriate +Legal Notices; however, if the Program has interactive interfaces that do +not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, +which are not by their nature extensions of the covered work, and which are +not combined with it such as to form a larger program, in or on a volume of +a storage or distribution medium, is called an "aggregate" if the compilation +and its resulting copyright are not used to limit the access or legal rights +of the compilation's users beyond what the individual works permit. Inclusion +of a covered work in an aggregate does not cause this License to apply to +the other parts of the aggregate. + + 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of sections +4 and 5, provided that you also convey the machine-readable Corresponding +Source under the terms of this License, in one of these ways: + +a) Convey the object code in, or embodied in, a physical product (including +a physical distribution medium), accompanied by the Corresponding Source fixed +on a durable physical medium customarily used for software interchange. + +b) Convey the object code in, or embodied in, a physical product (including +a physical distribution medium), accompanied by a written offer, valid for +at least three years and valid for as long as you offer spare parts or customer +support for that product model, to give anyone who possesses the object code +either (1) a copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical medium customarily +used for software interchange, for a price no more than your reasonable cost +of physically performing this conveying of source, or (2) access to copy the +Corresponding Source from a network server at no charge. + +c) Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is allowed only +occasionally and noncommercially, and only if you received the object code +with such an offer, in accord with subsection 6b. + +d) Convey the object code by offering access from a designated place (gratis +or for a charge), and offer equivalent access to the Corresponding Source +in the same way through the same place at no further charge. You need not +require recipients to copy the Corresponding Source along with the object +code. If the place to copy the object code is a network server, the Corresponding +Source may be on a different server (operated by you or a third party) that +supports equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. Regardless +of what server hosts the Corresponding Source, you remain obligated to ensure +that it is available for as long as needed to satisfy these requirements. + +e) Convey the object code using peer-to-peer transmission, provided you inform +other peers where the object code and Corresponding Source of the work are +being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from +the Corresponding Source as a System Library, need not be included in conveying +the object code work. + +A "User Product" is either (1) a "consumer product", which means any tangible +personal property which is normally used for personal, family, or household +purposes, or (2) anything designed or sold for incorporation into a dwelling. +In determining whether a product is a consumer product, doubtful cases shall +be resolved in favor of coverage. For a particular product received by a particular +user, "normally used" refers to a typical or common use of that class of product, +regardless of the status of the particular user or of the way in which the +particular user actually uses, or expects or is expected to use, the product. +A product is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent the +only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, procedures, +authorization keys, or other information required to install and execute modified +versions of a covered work in that User Product from a modified version of +its Corresponding Source. The information must suffice to ensure that the +continued functioning of the modified object code is in no case prevented +or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically +for use in, a User Product, and the conveying occurs as part of a transaction +in which the right of possession and use of the User Product is transferred +to the recipient in perpetuity or for a fixed term (regardless of how the +transaction is characterized), the Corresponding Source conveyed under this +section must be accompanied by the Installation Information. But this requirement +does not apply if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has been installed +in ROM). + +The requirement to provide Installation Information does not include a requirement +to continue to provide support service, warranty, or updates for a work that +has been modified or installed by the recipient, or for the User Product in +which it has been modified or installed. Access to a network may be denied +when the modification itself materially and adversely affects the operation +of the network or violates the rules and protocols for communication across +the network. + +Corresponding Source conveyed, and Installation Information provided, in accord +with this section must be in a format that is publicly documented (and with +an implementation available to the public in source code form), and must require +no special password or key for unpacking, reading or copying. + + 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this License +by making exceptions from one or more of its conditions. Additional permissions +that are applicable to the entire Program shall be treated as though they +were included in this License, to the extent that they are valid under applicable +law. If additional permissions apply only to part of the Program, that part +may be used separately under those permissions, but the entire Program remains +governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any +additional permissions from that copy, or from any part of it. (Additional +permissions may be written to require their own removal in certain cases when +you modify the work.) You may place additional permissions on material, added +by you to a covered work, for which you have or can give appropriate copyright +permission. + +Notwithstanding any other provision of this License, for material you add +to a covered work, you may (if authorized by the copyright holders of that +material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the terms of +sections 15 and 16 of this License; or + +b) Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices displayed +by works containing it; or + +c) Prohibiting misrepresentation of the origin of that material, or requiring +that modified versions of such material be marked in reasonable ways as different +from the original version; or + +d) Limiting the use for publicity purposes of names of licensors or authors +of the material; or + +e) Declining to grant rights under trademark law for use of some trade names, +trademarks, or service marks; or + +f) Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with contractual +assumptions of liability to the recipient, for any liability that these contractual +assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered "further restrictions" +within the meaning of section 10. If the Program as you received it, or any +part of it, contains a notice stating that it is governed by this License +along with a term that is a further restriction, you may remove that term. +If a license document contains a further restriction but permits relicensing +or conveying under this License, you may add to a covered work material governed +by the terms of that license document, provided that the further restriction +does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, +in the relevant source files, a statement of the additional terms that apply +to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form +of a separately written license, or stated as exceptions; the above requirements +apply either way. + + 8. Termination. + +You may not propagate or modify a covered work except as expressly provided +under this License. Any attempt otherwise to propagate or modify it is void, +and will automatically terminate your rights under this License (including +any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from +a particular copyright holder is reinstated (a) provisionally, unless and +until the copyright holder explicitly and finally terminates your license, +and (b) permanently, if the copyright holder fails to notify you of the violation +by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently +if the copyright holder notifies you of the violation by some reasonable means, +this is the first time you have received notice of violation of this License +(for any work) from that copyright holder, and you cure the violation prior +to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses +of parties who have received copies or rights from you under this License. +If your rights have been terminated and not permanently reinstated, you do +not qualify to receive new licenses for the same material under section 10. + + 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run a copy +of the Program. Ancillary propagation of a covered work occurring solely as +a consequence of using peer-to-peer transmission to receive a copy likewise +does not require acceptance. However, nothing other than this License grants +you permission to propagate or modify any covered work. These actions infringe +copyright if you do not accept this License. Therefore, by modifying or propagating +a covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically receives +a license from the original licensors, to run, modify and propagate that work, +subject to this License. You are not responsible for enforcing compliance +by third parties with this License. + +An "entity transaction" is a transaction transferring control of an organization, +or substantially all assets of one, or subdividing an organization, or merging +organizations. If propagation of a covered work results from an entity transaction, +each party to that transaction who receives a copy of the work also receives +whatever licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the Corresponding +Source of the work from the predecessor in interest, if the predecessor has +it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights +granted or affirmed under this License. For example, you may not impose a +license fee, royalty, or other charge for exercise of rights granted under +this License, and you may not initiate litigation (including a cross-claim +or counterclaim in a lawsuit) alleging that any patent claim is infringed +by making, using, selling, offering for sale, or importing the Program or +any portion of it. + + 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this License +of the Program or a work on which the Program is based. The work thus licensed +is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned or controlled +by the contributor, whether already acquired or hereafter acquired, that would +be infringed by some manner, permitted by this License, of making, using, +or selling its contributor version, but do not include claims that would be +infringed only as a consequence of further modification of the contributor +version. For purposes of this definition, "control" includes the right to +grant patent sublicenses in a manner consistent with the requirements of this +License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent +license under the contributor's essential patent claims, to make, use, sell, +offer for sale, import and otherwise run, modify and propagate the contents +of its contributor version. + +In the following three paragraphs, a "patent license" is any express agreement +or commitment, however denominated, not to enforce a patent (such as an express +permission to practice a patent or covenant not to s ue for patent infringement). +To "grant" such a patent license to a party means to make such an agreement +or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the +Corresponding Source of the work is not available for anyone to copy, free +of charge and under the terms of this License, through a publicly available +network server or other readily accessible means, then you must either (1) +cause the Corresponding Source to be so available, or (2) arrange to deprive +yourself of the benefit of the patent license for this particular work, or +(3) arrange, in a manner consistent with the requirements of this License, +to extend the patent + +license to downstream recipients. "Knowingly relying" means you have actual +knowledge that, but for the patent license, your conveying the covered work +in a country, or your recipient's use of the covered work in a country, would +infringe one or more identifiable patents in that country that you have reason +to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, +you convey, or propagate by procuring conveyance of, a covered work, and grant +a patent license to some of the parties receiving the covered work authorizing +them to use, propagate, modify or convey a specific copy of the covered work, +then the patent license you grant is automatically extended to all recipients +of the covered work and works based on it. + +A patent license is "discriminatory" if it does not include within the scope +of its coverage, prohibits the exercise of, or is conditioned on the non-exercise +of one or more of the rights that are specifically granted under this License. +You may not convey a covered work if you are a party to an arrangement with +a third party that is in the business of distributing software, under which +you make payment to the third party based on the extent of your activity of +conveying the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by you +(or copies made from those copies), or (b) primarily for and in connection +with specific products or compilations that contain the covered work, unless +you entered into that arrangement, or that patent license was granted, prior +to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied +license or other defenses to infringement that may otherwise be available +to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or otherwise) +that contradict the conditions of this License, they do not excuse you from +the conditions of this License. If you cannot convey a covered work so as +to satisfy simultaneously your obligations under this License and any other +pertinent obligations, then as a consequence you may + +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey the +Program, the only way you could satisfy both those terms and this License +would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + +Notwithstanding any other provision of this License, if you modify the Program, +your modified version must prominently offer all users interacting with it +remotely through a computer network (if your version supports such interaction) +an opportunity to receive the Corresponding Source of your version by providing +access to the Corresponding Source from a network server at no charge, through +some standard or customary means of facilitating copying of software. This +Corresponding Source shall include the Corresponding Source for any work covered +by version 3 of the GNU General Public License that is incorporated pursuant +to the following paragraph. + +Notwithstanding any other provision of this License, you have permission to +link or combine any covered work with a work licensed under version 3 of the +GNU General Public License into a single combined work, and to convey the +resulting work. The terms of this License will continue to apply to the part +which is the covered work, but the work with which it is combined will remain +governed by version 3 of the GNU General Public License. + + 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of the +GNU Affero General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address +new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +that a certain numbered version of the GNU Affero General Public License "or +any later version" applies to it, you have the option of following the terms +and conditions either of that numbered version or of any later version published +by the Free Software Foundation. If the Program does not specify a version +number of the GNU Affero General Public License, you may choose any version +ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of +the GNU Affero General Public License can be used, that proxy's public statement +of acceptance of a version permanently authorizes you to choose that version +for the Program. + +Later license versions may give you additional or different permissions. However, +no additional obligations are imposed on any author or copyright holder as +a result of your choosing to follow a later version. + + 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM +PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM +AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO +USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE +PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided above cannot +be given local legal effect according to their terms, reviewing courts shall +apply local law that most closely approximates an absolute waiver of all civil +liability in connection with the Program, unless a warranty or assumption +of liability accompanies a copy of the Program in return for a fee. END OF +TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively state the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU Affero General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +details. + +You should have received a copy of the GNU Affero General Public License along +with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer network, +you should also make sure that it provides a way for users to get its source. +For example, if your program is a web application, its interface could display +a "Source" link that leads users to an archive of the code. There are many +ways you could offer source, and different solutions will be better for different +programs; see section 13 for the specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. For +more information on this, and how to apply and follow the GNU AGPL, see . diff --git a/devscripts/gen-vendor-tarball.sh b/devscripts/gen-vendor-tarball.sh new file mode 100755 index 0000000..eba038f --- /dev/null +++ b/devscripts/gen-vendor-tarball.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +PACKAGE="xcp-metrics" +#VERSION=$(git describe --always "HEAD") +VERSION="$1" + +# For this plugin, comment out patched xenstore-rs +CARGOTOML=plugins/xcp-metrics-plugin-common/Cargo.toml +awk < $CARGOTOML > $CARGOTOML.patched ' + BEGIN {p=1}; + /^\[dependencies.xenstore-rs-wip\]/ {p=0}; + /^$/ {p=1}; + { if (p==1) {print} else { print "#" $0}}' +mv $CARGOTOML.patched $CARGOTOML +# remove reference to xenstore-rs-wip +sed -i '/^xenstore-wip = / d' \ + plugins/xcp-metrics-plugin-common/Cargo.toml + +cargo vendor --versioned-dirs third-party +tar -zcf "../$PACKAGE-$VERSION-vendor.tar.gz" --xform="s,^,$PACKAGE-$VERSION/," third-party/ diff --git a/metrics_sample/xcp-rrdd-mem_host b/metrics_sample/xcp-rrdd-mem_host new file mode 100644 index 0000000000000000000000000000000000000000..de5949436c30dc3a90b1e9fa98131c9303e9647c GIT binary patch literal 4096 zcmeH^zfQw25XKEW1G{w_QiUQYQRr6wbYVcEWsXeav=)h7IcI29W#kDM5G(HkkJ4x0 zoOZ3m!ghmw`aa*C?tZ=*PKM+A$A|0N@y{`i;OpdD2ysY96rXP&F^YV%?BeLC5aQr{ z4TVD0xZtO{fx#MTT|2+Z(V?pHXY&-jLN`-y7HFJ>0ZihPRJ98hr7PvOLK-V^uI1b{ z2t9DGR(nd`$rn`xO)@>p(#tfXgwDxvwTQN{nD)us$(af>O|sCX3KdcUdMfWhum)*L zxHDIzY7@svPLm`Gwd@*|(303LQF^WawnNO^EkeEa4Bx-Vvh(bphi}{Nd-!4kOn?b6 W0Vco%m;e)C0!)AjFaaj8m%uMkLyl4a literal 0 HcmV?d00001 diff --git a/metrics_sample/xcp-rrdd-xenpm b/metrics_sample/xcp-rrdd-xenpm new file mode 100644 index 0000000000000000000000000000000000000000..fae922571fc1b9801882e4500f016a156d1671b6 GIT binary patch literal 32768 zcmeIzzl+mg9LMoY$4yQJmm5M*IH3*s-S$LmsBWUioi}S}QjD}oNS>TOjtX)(%FPar zZcYx);-UxD!A-4_unr+f7LnT zx2Bh_&F3Em$2;dAubunqx8jqHm+PjYtUW!@!axK?TIQpu(6$b=QC1qAp;5gJqhgfD znTXRw+tRl4G)wbpP}8w0;%TG~xA#;-EwU&PYMiLUP9XvjsfO0p(tAmi%TL`&3n9n- zU{XeMG@Y*9*A4sc(k<~ItJcSpG^qBSj$xF?`;nZ(XdILiA$N#e-k`0ONi5_!wasxJ zjH<(2kc-o}I-sE&)i+Or`*JX=Vb(s4WByMZQ{MC+actZ2dY<0x%PoH*Hj&4yQ;%7% z9<$f=bjxZu&g%6nh_kdF*LC{3SN$v+tH-KSk5#W8tLr+t+jN}O>sb(IX+4hDHFdku zr-5Ck9=m2eeb3RYMjr+;&g%6nh_k#N$1`=esd{F!>W_^J0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ j0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILSSIir3vw>! literal 0 HcmV?d00001 diff --git a/plugins/xcp-metrics-plugin-common/Cargo.toml b/plugins/xcp-metrics-plugin-common/Cargo.toml new file mode 100644 index 0000000..3f9e7a6 --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "xcp-metrics-plugin-common" +description = "Library that helps making plugins for xcp-metrics and xcp-rrdd" +version.workspace = true +license = "AGPL-3.0-only" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +xcp-metrics-common = { path = "../../xcp-metrics-common" } +xapi = { path = "../../xapi-rs" } + +anyhow = "1.0" +tokio = "1" +uuid = "1.4" +tracing = "0.1" +tracing-subscriber = "0.3" + +dashmap = "5.5" +futures = "0.3" + +[dependencies.xenstore-rs] +version = "0.3" +optional = true + +[dependencies.xenstore-rs-wip] +package = "xenstore-rs" +optional = true + +[features] +default = [] +xenstore = ["dep:xenstore-rs"] +xenstore-wip = ["xenstore", "dep:xenstore-rs-wip"] diff --git a/plugins/xcp-metrics-plugin-common/src/bridge/mod.rs b/plugins/xcp-metrics-plugin-common/src/bridge/mod.rs new file mode 100644 index 0000000..b2cff8d --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/bridge/mod.rs @@ -0,0 +1,3 @@ +//! Bridges for conversion beteen protocol v2 and protocol v3. + +pub mod v3_to_v2; diff --git a/plugins/xcp-metrics-plugin-common/src/bridge/v3_to_v2.rs b/plugins/xcp-metrics-plugin-common/src/bridge/v3_to_v2.rs new file mode 100644 index 0000000..281739f --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/bridge/v3_to_v2.rs @@ -0,0 +1,142 @@ +//! Adapter to convert from protocol v3 to protocol v2. +use std::{collections::HashMap, iter}; + +use xcp_metrics_common::{ + metrics::{Label, Metric, MetricFamily, MetricPoint, MetricSet, MetricValue}, + rrdd::{ + protocol_common::{DataSourceMetadata, DataSourceValue}, + protocol_v2::{indexmap::IndexMap, RrddMetadata}, + }, + utils::{ + delta::MetricSetModel, + mapping::{CustomMapping, DefaultMapping, MetadataMapping}, + }, +}; + +/// Adapter to convert protocol v3 metrics set into protocol v2 metadata and data. +pub struct BridgeToV2 { + model: MetricSetModel, + latest_set: MetricSet, + custom_mappings: HashMap, CustomMapping>, + + metadata: RrddMetadata, + metadata_map: Vec<(Box, Box<[Label]>)>, +} + +/// Convert a MetricPoint into a protocol-v2 value. +fn metric_point_to_v2(metric_point: &MetricPoint) -> DataSourceValue { + match metric_point.value { + MetricValue::Gauge(value) => DataSourceValue::from(value), + MetricValue::Counter { total, .. } => DataSourceValue::from(total), + _ => DataSourceValue::Undefined, + } +} + +impl BridgeToV2 { + pub fn new() -> Self { + Self { + model: MetricSetModel::default(), + latest_set: MetricSet::default(), + custom_mappings: HashMap::default(), + metadata: RrddMetadata { + datasources: IndexMap::default(), + }, + metadata_map: vec![], + } + } + + pub fn with_mappings(custom_mappings: HashMap, CustomMapping>) -> Self { + Self { + custom_mappings, + ..Default::default() + } + } + + fn metric_to_v2_metadata( + &self, + family_name: &str, + family: &MetricFamily, + metric: &Metric, + ) -> Option<(Box, DataSourceMetadata)> { + if let Some(custom_mapping) = self.custom_mappings.get(family_name) { + custom_mapping.convert(family_name, family, metric) + } else { + DefaultMapping.convert(family_name, family, metric) + } + } + + /// Update bridge information, returns true on metadata change. + pub fn update(&mut self, metrics_set: MetricSet) -> bool { + let delta = self.model.compute_delta(&metrics_set); + self.model.apply_delta(&delta); + + if !delta.added_families.is_empty() + || !delta.added_metrics.is_empty() + || !delta.removed_metrics.is_empty() + { + self.latest_set = metrics_set; + self.reset_metadata(); + true + } else { + self.latest_set = metrics_set; + false + } + } + + pub fn get_data(&self) -> Box<[DataSourceValue]> { + self.metadata_map + .iter() + .filter_map(|(family_name, labels)| self.get_first_metric_point(family_name, labels)) + .map(metric_point_to_v2) + .collect::>() + } + + pub fn get_metadata(&self) -> &RrddMetadata { + &self.metadata + } + + fn get_first_metric_point<'a>( + &'a self, + family_name: &str, + labels: &[Label], + ) -> Option<&'a MetricPoint> { + self.latest_set + .families + .get(family_name) + .and_then(|family| { + family + .metrics + .iter() + // Filter by labels + .filter(|(_, metric)| metric.labels.as_ref() == labels) + // Only take first metrics_point + .find_map(|(_, metric)| metric.metrics_point.first()) + }) + } + + fn reset_metadata(&mut self) { + let (datasources, metadata_map) = self + .latest_set + .families + .iter() + // Combine family with family name and metrics. + .flat_map(|(name, family)| { + iter::zip(iter::repeat((name, family)), family.metrics.iter()) + }) + // Convert this data to protocol v2 metadata and mapping information. + .filter_map(|((family_name, family), (_, metric))| { + self.metric_to_v2_metadata(family_name, family, metric) + .map(|mapping| (mapping, (family_name.clone(), metric.labels.clone()))) + }) + .unzip(); + + self.metadata = RrddMetadata { datasources }; + self.metadata_map = metadata_map; + } +} + +impl Default for BridgeToV2 { + fn default() -> Self { + Self::new() + } +} diff --git a/plugins/xcp-metrics-plugin-common/src/lib.rs b/plugins/xcp-metrics-plugin-common/src/lib.rs new file mode 100644 index 0000000..3750e47 --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/lib.rs @@ -0,0 +1,7 @@ +pub mod bridge; +pub mod plugin; +pub mod protocol_v2; +pub mod protocol_v3; + +#[cfg(feature = "xenstore")] +pub mod xenstore; diff --git a/plugins/xcp-metrics-plugin-common/src/plugin.rs b/plugins/xcp-metrics-plugin-common/src/plugin.rs new file mode 100644 index 0000000..5c878b6 --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/plugin.rs @@ -0,0 +1,143 @@ +//! Utilities that manages communication with daemon using protocol v3 +//! under the hood and converting to protocol v2 if needed. +use std::{collections::HashMap, path::Path, time::Duration}; + +use tokio::time; + +use crate::{ + bridge::v3_to_v2::BridgeToV2, + protocol_v2::RrddPlugin, + protocol_v3::{utils::SimpleMetricSet, MetricsPlugin}, +}; +use xcp_metrics_common::utils::mapping::CustomMapping; + +pub const XCP_RRDD_PATH: &str = "/var/lib/xcp/xcp-rrdd"; + +/// Abstraction of a protocol v3 plugin. +pub trait XcpPlugin { + /// Update the state of the plugin. + fn update(&mut self); + + // Generate a new metric set representing the current state of data. + fn generate_metrics(&mut self) -> SimpleMetricSet; + + /// Get the plugin name (uid). + fn get_name(&self) -> &str; + + // Get plugin mappings + fn get_mappings(&self) -> Option, CustomMapping>>; +} + +fn arg0_starts_with_rrdp() -> bool { + let Some(arg0) = std::env::args().next() else { + return false; + }; + + Path::new(&arg0) + .file_name() + .unwrap_or_default() + .to_os_string() + .to_string_lossy() + .starts_with("rrdp-") +} + +/// Run the provided for either protocol v2 (converting from v3) or protocol v3 depending on `version`. +/// +/// Versions : +/// 2: Use a internal v3 to v2 bridge with `mappings` to convert from protocol v3 to protocol v2. +/// 3: Directly expose protocol v3 metrics to target daemon. +/// +/// If no target_daemon is provided, use default one. +pub async fn run_hybrid( + shared: impl XcpPlugin, + mut target_daemon_path: Option<&Path>, + mut version: Option, +) { + if target_daemon_path.is_none() && version.is_none() && arg0_starts_with_rrdp() { + tracing::info!("Program name starts with rrdp-*, use xcp-rrdd and protocol-v2 by default."); + target_daemon_path = Some(Path::new(&XCP_RRDD_PATH)); + version = Some(2); + } + + match version.unwrap_or(3) { + 2 => run_plugin_v2(shared, target_daemon_path).await, + 3 => run_plugin_v3(shared, target_daemon_path).await, + p => tracing::error!("Unknown protocol {p}"), + } +} + +pub async fn run_plugin_v2(mut shared: impl XcpPlugin, target_daemon_path: Option<&Path>) { + tracing::info!("Running protocol v2 plugin: {}", shared.get_name()); + let mut metrics = shared.generate_metrics(); + + let mut bridge = BridgeToV2::with_mappings(shared.get_mappings().unwrap_or_default()); + bridge.update(metrics.into()); + + let mut plugin = match RrddPlugin::new( + shared.get_name(), + bridge.get_metadata().clone(), + Some(&bridge.get_data()), + target_daemon_path, + ) + .await + { + Ok(plugin) => plugin, + Err(e) => { + tracing::error!("Unable to initialize plugin ({e})"); + return; + } + }; + + // Expose protocol v2 + loop { + tracing::debug!("Updating plugin state"); + + // Update sources + shared.update(); + + // Fetch and push new metrics. + metrics = shared.generate_metrics(); + + if bridge.update(metrics.into()) { + if let Err(e) = plugin + .reset_metadata(bridge.get_metadata().clone(), Some(&bridge.get_data())) + .await + { + tracing::warn!("Unable to update metadata ({e}"); + } + } + + if let Err(e) = plugin.update_values(&bridge.get_data()).await { + tracing::warn!("Unable to update plugin values ({e})"); + } + + time::sleep(Duration::from_secs(1)).await; + } +} + +pub async fn run_plugin_v3(mut shared: impl XcpPlugin, target_daemon_path: Option<&Path>) { + tracing::info!("Running protocol v3 plugin: {}", shared.get_name()); + // Expose protocol v3 + // NOTE: some could be undefined values + let plugin = MetricsPlugin::new( + &shared.get_name().to_string(), + shared.generate_metrics().into(), + target_daemon_path, + ) + .await + .unwrap(); + + loop { + tracing::debug!("Updating plugin state"); + // Update sources + shared.update(); + + // Fetch and push new metrics. + plugin + .update(shared.generate_metrics().into()) + .await + .unwrap(); + + time::sleep(Duration::from_secs(1)).await; + } +} diff --git a/plugins/xcp-metrics-plugin-common/src/protocol_v2.rs b/plugins/xcp-metrics-plugin-common/src/protocol_v2.rs new file mode 100644 index 0000000..055121a --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/protocol_v2.rs @@ -0,0 +1,170 @@ +use std::path::{Path, PathBuf}; + +use tokio::{ + fs::{create_dir_all, OpenOptions}, + io::AsyncWriteExt, +}; +use xapi::{ + rpc::{ + message::parse_http_response, + methods::{PluginLocalDeregister, PluginLocalRegister}, + }, + METRICS_SHM_PATH, +}; +use xcp_metrics_common::rrdd::{ + protocol_common::DataSourceValue, + protocol_v2::{values_to_raw, RrddMessageHeader, RrddMetadata}, +}; + +pub struct RrddPlugin { + uid: Box, + header: RrddMessageHeader, + metrics_path: PathBuf, + target_daemon_path: PathBuf, +} + +const DEFAULT_DAEMON: &str = "/var/lib/xcp/xcp-metrics"; + +impl RrddPlugin { + /// Create and register a new plugin. + pub async fn new( + uid: &'_ str, + metadata: RrddMetadata, + initial_values: Option<&[DataSourceValue]>, + target_daemon_path: Option<&Path>, + ) -> anyhow::Result { + let (header, metadata_str) = Self::generate_initial_header(metadata, initial_values); + + let plugin = Self { + uid: uid.into(), + header, + metrics_path: Path::new(METRICS_SHM_PATH).join(uid), + target_daemon_path: target_daemon_path + .unwrap_or(Path::new(DEFAULT_DAEMON)) + .to_path_buf(), + }; + + plugin.reset_file(Some(&metadata_str)).await?; + plugin.advertise_plugin().await?; + + Ok(plugin) + } + + /// Push new values to the shared file. + /// + /// # Condition + /// The length of `new_values` must match the latest sent metadata (either by [Self::new] or [Self::reset_metadata]). + pub async fn update_values(&mut self, new_values: &[DataSourceValue]) -> anyhow::Result<()> { + self.header.update_values(&values_to_raw(new_values))?; + self.reset_file(None).await + } + + /// Advertise the existence of the plugin to the main daemon. + pub async fn advertise_plugin(&self) -> anyhow::Result<()> { + let request = PluginLocalRegister { + info: "Five_Seconds".into(), + protocol: "V2".into(), + uid: self.uid.to_string(), + }; + + let response = xapi::send_xmlrpc_to( + &self.target_daemon_path, + "POST", + &request, + &self.uid, /* use uid as user-agent */ + ) + .await + .map_err(|e| { + anyhow::anyhow!( + "Can't reach '{}' daemon ({e})", + self.target_daemon_path.to_string_lossy() + ) + })?; + + tracing::info!("RPC Response: {:?}", parse_http_response(response).await); + + Ok(()) + } + + /// Replace the metadata of the shared file. + /// + /// # Condition + /// The length of `initial_values` must match the `metadata`. + pub async fn reset_metadata( + &mut self, + metadata: RrddMetadata, + initial_values: Option<&[DataSourceValue]>, + ) -> anyhow::Result<()> { + let (header, metadata_str) = + Self::generate_initial_header(metadata.clone(), initial_values); + + self.header = header; + self.reset_file(Some(&metadata_str)).await + } + + async fn reset_file(&self, raw_metadata: Option<&str>) -> anyhow::Result<()> { + // Create directory if doesn't exist. + create_dir_all(METRICS_SHM_PATH).await?; + + let mut options = OpenOptions::new(); + options.create(true); + options.truncate(false); + options.write(true); + + let mut file = options.open(&self.metrics_path).await?; + + let mut header_buffer = vec![]; + self.header.write(&mut header_buffer)?; + file.write_all(&header_buffer).await?; + + if let Some(raw_metadata) = raw_metadata { + file.write_all(raw_metadata.as_bytes()).await?; + } + + Ok(()) + } + + fn generate_initial_header( + metadata: RrddMetadata, + initial_values: Option<&[DataSourceValue]>, + ) -> (RrddMessageHeader, Box) { + let raw_values = if let Some(init) = initial_values { + values_to_raw(init) + } else { + vec![[0; 8]; metadata.datasources.len()].into_boxed_slice() + }; + + RrddMessageHeader::generate(&raw_values, metadata) + } + + /// Deregister the plugin from the daemon. + pub async fn deregister_plugin(self) { + tracing::info!("Deregistering {}...", &self.uid); + + // Unregister plugin + let request = PluginLocalDeregister { + uid: self.uid.to_string(), + }; + + match xapi::send_xmlrpc_to( + &self.target_daemon_path, + "POST", + &request, + &self.uid, /* use uid as user-agent */ + ) + .await + { + Ok(response) => { + tracing::info!("RPC Response: {:?}", parse_http_response(response).await); + } + Err(e) => { + tracing::error!("Unable to unregister plugin ({e})") + } + } + + // Delete plugin file. + if let Err(e) = tokio::fs::remove_file(self.metrics_path).await { + tracing::warn!("Unable to remove plugin file: {e}"); + } + } +} diff --git a/plugins/xcp-metrics-plugin-common/src/protocol_v3/mod.rs b/plugins/xcp-metrics-plugin-common/src/protocol_v3/mod.rs new file mode 100644 index 0000000..20ff885 --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/protocol_v3/mod.rs @@ -0,0 +1,116 @@ +//! xcp-metrics plugin protocol v3 framework. +pub mod utils; + +use std::path::{Path, PathBuf}; + +use tokio::fs::{create_dir_all, OpenOptions}; +use xapi::{ + rpc::{ + message::parse_http_response, + methods::{PluginMetricsDeregister, PluginMetricsRegister}, + }, + METRICS_SHM_PATH, +}; +use xcp_metrics_common::{metrics::MetricSet, protocol_v3}; + +pub struct MetricsPlugin { + uid: Box, + metrics_path: PathBuf, + target_daemon_path: PathBuf, +} + +const DEFAULT_DAEMON: &str = "/var/lib/xcp/xcp-metrics"; + +impl MetricsPlugin { + /// Create and register a new plugin. + pub async fn new( + uid: &'_ str, + metrics: MetricSet, + target_daemon_path: Option<&Path>, + ) -> anyhow::Result { + let plugin = Self { + uid: uid.into(), + metrics_path: Path::new(METRICS_SHM_PATH).join(uid), + target_daemon_path: target_daemon_path + .unwrap_or(Path::new(DEFAULT_DAEMON)) + .to_path_buf(), + }; + + plugin.update(metrics).await?; + plugin.advertise_plugin().await?; + + Ok(plugin) + } + + pub async fn update(&self, metrics: MetricSet) -> anyhow::Result<()> { + create_dir_all(METRICS_SHM_PATH).await?; + + let mut options = OpenOptions::new(); + options.create(true); + options.truncate(false); + options.write(true); + + let mut file = options.open(&self.metrics_path).await?; + + protocol_v3::generate_v3_async(&mut file, None, metrics).await?; + + Ok(()) + } + + /// Advertise the existence of the plugin to the main daemon. + pub async fn advertise_plugin(&self) -> anyhow::Result<()> { + let request = PluginMetricsRegister { + version: "OpenMetrics 1.0.0".into(), + uid: self.uid.to_string(), + }; + + let response = xapi::send_xmlrpc_to( + &self.target_daemon_path, + "POST", + &request, + &self.uid, /* use uid as user-agent */ + ) + .await + .map_err(|e| { + anyhow::anyhow!( + "Can't reach '{}' daemon ({e})", + self.target_daemon_path.to_string_lossy() + ) + })?; + + tracing::debug!("RPC Response: {:?}", parse_http_response(response).await); + + Ok(()) + } + + /// Deregister the plugin from the daemon. + pub async fn deregister_plugin(self) { + tracing::info!("Deregistering {}...", &self.uid); + + // Unregister plugin + let request = PluginMetricsDeregister { + uid: self.uid.to_string(), + }; + + match xapi::send_xmlrpc_to( + &self.target_daemon_path, + "POST", + &request, + &self.uid, /* use uid as user-agent */ + ) + .await + { + Ok(response) => { + tracing::debug!("RPC Response: {:?}", parse_http_response(response).await); + } + Err(e) => { + tracing::error!("Unable to unregister plugin ({e})"); + } + } + + // Delete plugin file. + if let Err(e) = tokio::fs::remove_file(self.metrics_path).await { + tracing::warn!("Unable to remove plugin file: {e}"); + } + } +} diff --git a/plugins/xcp-metrics-plugin-common/src/protocol_v3/utils.rs b/plugins/xcp-metrics-plugin-common/src/protocol_v3/utils.rs new file mode 100644 index 0000000..092b58b --- /dev/null +++ b/plugins/xcp-metrics-plugin-common/src/protocol_v3/utils.rs @@ -0,0 +1,72 @@ +//! Simpler metrics representation for plugins. + +use std::{collections::HashMap, time::SystemTime}; + +use xcp_metrics_common::metrics::{ + Label, Metric, MetricFamily, MetricPoint, MetricSet, MetricType, MetricValue, +}; + +#[derive(Clone, Debug)] +pub struct SimpleMetricSet { + pub families: HashMap, +} + +impl From for MetricSet { + fn from(SimpleMetricSet { families }: SimpleMetricSet) -> Self { + Self { + families: families + .into_iter() + .map(|(name, family)| (name.into_boxed_str(), family.into())) + .collect(), + } + } +} + +#[derive(Clone, Debug)] +pub struct SimpleMetricFamily { + pub metric_type: MetricType, + pub unit: Box, + pub help: Box, + + pub metrics: Vec, +} + +impl From for MetricFamily { + fn from( + SimpleMetricFamily { + metric_type, + unit, + help, + metrics, + }: SimpleMetricFamily, + ) -> Self { + Self { + metric_type, + unit, + help, + metrics: metrics + .into_iter() + .map(|simple_metric| (uuid::Uuid::new_v4(), Metric::from(simple_metric))) + .collect(), + } + } +} + +#[derive(Clone, Debug)] +pub struct SimpleMetric { + pub labels: Vec