From 425f7baaeb29ce69d01ca384cf28d2232acba163 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 06:21:10 +0000 Subject: [PATCH 01/25] build(deps): bump postcss and next in /striker-ui Bumps [postcss](https://github.com/postcss/postcss) to 8.4.31 and updates ancestor dependency [next](https://github.com/vercel/next.js). These dependencies need to be updated together. Updates `postcss` from 8.4.5 to 8.4.31 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.5...8.4.31) Updates `next` from 12.1.0 to 13.5.4 - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](https://github.com/vercel/next.js/compare/v12.1.0...v13.5.4) --- updated-dependencies: - dependency-name: postcss dependency-type: indirect - dependency-name: next dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- striker-ui/package-lock.json | 512 ++++++++++++++++++++++++++--------- striker-ui/package.json | 2 +- 2 files changed, 378 insertions(+), 136 deletions(-) diff --git a/striker-ui/package-lock.json b/striker-ui/package-lock.json index da71ae6b..ecc6b3ab 100644 --- a/striker-ui/package-lock.json +++ b/striker-ui/package-lock.json @@ -25,7 +25,7 @@ "formik": "^2.4.3", "lodash": "^4.17.21", "netmask": "^2.0.2", - "next": "^12.1.0", + "next": "^13.5.4", "pretty-bytes": "^5.6.0", "react": "17.0.2", "react-dom": "17.0.2", @@ -1444,9 +1444,9 @@ } }, "node_modules/@next/env": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz", - "integrity": "sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ==" + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", + "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" }, "node_modules/@next/eslint-plugin-next": { "version": "11.1.4", @@ -1457,10 +1457,70 @@ "glob": "7.1.7" } }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", + "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz", - "integrity": "sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", "cpu": [ "x64" ], @@ -1473,9 +1533,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz", - "integrity": "sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", "cpu": [ "x64" ], @@ -1487,6 +1547,51 @@ "node": ">= 10" } }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1542,6 +1647,14 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "dev": true }, + "node_modules/@swc/helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", @@ -2145,6 +2258,17 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -2193,13 +2317,23 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001312", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", - "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } + "version": "1.0.30001546", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", + "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, "node_modules/chalk": { "version": "4.1.2", @@ -2254,6 +2388,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3599,6 +3738,11 @@ "node": ">= 6" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, "node_modules/global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -3649,8 +3793,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/hard-rejection": { "version": "2.1.0", @@ -4796,9 +4939,15 @@ } }, "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -4821,47 +4970,43 @@ } }, "node_modules/next": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/next/-/next-12.1.0.tgz", - "integrity": "sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==", - "dependencies": { - "@next/env": "12.1.0", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", + "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", + "dependencies": { + "@next/env": "13.5.4", + "@swc/helpers": "0.5.2", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.31", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=12.22.0" + "node": ">=16.14.0" }, "optionalDependencies": { - "@next/swc-android-arm64": "12.1.0", - "@next/swc-darwin-arm64": "12.1.0", - "@next/swc-darwin-x64": "12.1.0", - "@next/swc-linux-arm-gnueabihf": "12.1.0", - "@next/swc-linux-arm64-gnu": "12.1.0", - "@next/swc-linux-arm64-musl": "12.1.0", - "@next/swc-linux-x64-gnu": "12.1.0", - "@next/swc-linux-x64-musl": "12.1.0", - "@next/swc-win32-arm64-msvc": "12.1.0", - "@next/swc-win32-ia32-msvc": "12.1.0", - "@next/swc-win32-x64-msvc": "12.1.0" + "@next/swc-darwin-arm64": "13.5.4", + "@next/swc-darwin-x64": "13.5.4", + "@next/swc-linux-arm64-gnu": "13.5.4", + "@next/swc-linux-arm64-musl": "13.5.4", + "@next/swc-linux-x64-gnu": "13.5.4", + "@next/swc-linux-x64-musl": "13.5.4", + "@next/swc-win32-arm64-msvc": "13.5.4", + "@next/swc-win32-ia32-msvc": "13.5.4", + "@next/swc-win32-x64-msvc": "13.5.4" }, "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", + "@opentelemetry/api": "^1.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { + "@opentelemetry/api": { "optional": true }, "sass": { @@ -5206,20 +5351,30 @@ } }, "node_modules/postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "nanoid": "^3.1.30", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" }, "engines": { "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" } }, "node_modules/prelude-ls": { @@ -5897,6 +6052,14 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6058,14 +6221,17 @@ } }, "node_modules/styled-jsx": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz", - "integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, "engines": { "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || 18.x.x" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -6253,9 +6419,9 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -6348,17 +6514,6 @@ "punycode": "^2.1.0" } }, - "node_modules/use-subscription": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", - "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", - "dependencies": { - "object-assign": "^4.1.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -6388,6 +6543,18 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7527,9 +7694,9 @@ } }, "@next/env": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz", - "integrity": "sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ==" + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", + "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" }, "@next/eslint-plugin-next": { "version": "11.1.4", @@ -7540,16 +7707,58 @@ "glob": "7.1.7" } }, + "@next/swc-darwin-arm64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", + "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", + "optional": true + }, + "@next/swc-darwin-x64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "optional": true + }, "@next/swc-linux-x64-gnu": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz", - "integrity": "sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", "optional": true }, "@next/swc-linux-x64-musl": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz", - "integrity": "sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw==", + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "optional": true + }, + "@next/swc-win32-ia32-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", "optional": true }, "@nodelib/fs.scandir": { @@ -7594,6 +7803,14 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "dev": true }, + "@swc/helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "requires": { + "tslib": "^2.4.0" + } + }, "@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", @@ -8034,6 +8251,14 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -8067,9 +8292,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001312", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", - "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==" + "version": "1.0.30001546", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", + "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==" }, "chalk": { "version": "4.1.2", @@ -8106,6 +8331,11 @@ "string-width": "^4.2.0" } }, + "client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, "cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -9142,6 +9372,11 @@ "is-glob": "^4.0.1" } }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -9177,8 +9412,7 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "hard-rejection": { "version": "2.1.0", @@ -10065,9 +10299,9 @@ } }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "natural-compare": { "version": "1.4.0", @@ -10081,26 +10315,26 @@ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" }, "next": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/next/-/next-12.1.0.tgz", - "integrity": "sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==", - "requires": { - "@next/env": "12.1.0", - "@next/swc-android-arm64": "12.1.0", - "@next/swc-darwin-arm64": "12.1.0", - "@next/swc-darwin-x64": "12.1.0", - "@next/swc-linux-arm-gnueabihf": "12.1.0", - "@next/swc-linux-arm64-gnu": "12.1.0", - "@next/swc-linux-arm64-musl": "12.1.0", - "@next/swc-linux-x64-gnu": "12.1.0", - "@next/swc-linux-x64-musl": "12.1.0", - "@next/swc-win32-arm64-msvc": "12.1.0", - "@next/swc-win32-ia32-msvc": "12.1.0", - "@next/swc-win32-x64-msvc": "12.1.0", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", + "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", + "requires": { + "@next/env": "13.5.4", + "@next/swc-darwin-arm64": "13.5.4", + "@next/swc-darwin-x64": "13.5.4", + "@next/swc-linux-arm64-gnu": "13.5.4", + "@next/swc-linux-arm64-musl": "13.5.4", + "@next/swc-linux-x64-gnu": "13.5.4", + "@next/swc-linux-x64-musl": "13.5.4", + "@next/swc-win32-arm64-msvc": "13.5.4", + "@next/swc-win32-ia32-msvc": "13.5.4", + "@next/swc-win32-x64-msvc": "13.5.4", + "@swc/helpers": "0.5.2", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.31", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0" } }, "node-releases": { @@ -10341,13 +10575,13 @@ } }, "postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.1.30", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" } }, "prelude-ls": { @@ -10839,6 +11073,11 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10965,10 +11204,12 @@ "dev": true }, "styled-jsx": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz", - "integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==", - "requires": {} + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "requires": { + "client-only": "0.0.1" + } }, "stylis": { "version": "4.0.13", @@ -11113,9 +11354,9 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "tsutils": { "version": "3.21.0", @@ -11182,14 +11423,6 @@ "punycode": "^2.1.0" } }, - "use-subscription": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", - "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", - "requires": { - "object-assign": "^4.1.1" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11216,6 +11449,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/striker-ui/package.json b/striker-ui/package.json index 79ea8e2d..a87b81c4 100644 --- a/striker-ui/package.json +++ b/striker-ui/package.json @@ -30,7 +30,7 @@ "formik": "^2.4.3", "lodash": "^4.17.21", "netmask": "^2.0.2", - "next": "^12.1.0", + "next": "^13.5.4", "pretty-bytes": "^5.6.0", "react": "17.0.2", "react-dom": "17.0.2", From 62fe62a44b6ab6fe0028d56a739d043bffa4ba00 Mon Sep 17 00:00:00 2001 From: digimer Date: Mon, 11 Sep 2023 17:45:16 -0400 Subject: [PATCH 02/25] * Continued work on anvil-manage-server-system. It now displays the boot devices, CPU and RAM info. Signed-off-by: digimer --- man/anvil-manage-server-storage.8 | 2 +- man/anvil-manage-server-system.8 | 38 +++ share/words.xml | 2 + tools/anvil-manage-server-system | 486 ++++++++++++++++++++++++++++++ 4 files changed, 527 insertions(+), 1 deletion(-) create mode 100644 man/anvil-manage-server-system.8 create mode 100755 tools/anvil-manage-server-system diff --git a/man/anvil-manage-server-storage.8 b/man/anvil-manage-server-storage.8 index d7c9c79c..2e2c23f7 100644 --- a/man/anvil-manage-server-storage.8 +++ b/man/anvil-manage-server-storage.8 @@ -42,7 +42,7 @@ This is the disk being worked on. For optical disks, it's the drive that an opti When not specified, if only one disk exists, it will be chosen automatically. .TP \fB\-\-eject\fR -This ejects the optical disc (ISO) in the drive specified by \fB\-\-disk\fR. +This ejects the optical disc (ISO) in the drive specified by \fB\-\-optical\fR. .TP \fB\-\-job\-uuid\fR This is the jobs -> job_uuid to execute. Generally this is only used by other programs. diff --git a/man/anvil-manage-server-system.8 b/man/anvil-manage-server-system.8 new file mode 100644 index 00000000..70ff1629 --- /dev/null +++ b/man/anvil-manage-server-system.8 @@ -0,0 +1,38 @@ +.\" Manpage for the Anvil! server system manager +.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. +.TH anvil-manage-server-system "8" "August 30 2023" "Anvil! Intelligent Availability™ Platform" +.SH NAME +anvil-manage-server-system \- Tool used to manage the system configuration of a hosted server. +.SH SYNOPSIS +.B anvil-manage-server-system +\fI\, \/\fR[\fI\,options\/\fR] +.SH DESCRIPTION +anvil-manage-server-system \- This tool is used to manage various system configuration components of hosted servers. Storage is NOT managed here, see 'anvil-manage-server-storage' for that. +.TP +When called without switches, the list of servers than can be worked on will be displayed. +.TP +.SH OPTIONS +.TP +\-?, \-h, \fB\-\-help\fR +Show this man page. +.TP +\fB\-\-log-secure\fR +When logging, record sensitive data, like passwords. +.TP +\-v, \-vv, \-vvv +Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data. +.SS "Commands:" +.TP +\fB\-\-\fR + +.TP +\fB\-\-job\-uuid\fR +This is the jobs -> job_uuid to execute. Generally this is only used by other programs. +.TP +\fB\-\-\fR + +.IP +.SH AUTHOR +Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. +.SH "REPORTING BUGS" +Report bugs to users@clusterlabs.org diff --git a/share/words.xml b/share/words.xml index 8b851e10..e9fc241f 100644 --- a/share/words.xml +++ b/share/words.xml @@ -1149,6 +1149,7 @@ resource #!variable!server!# { On Battery Estimated Runtime Last Updated + Optical Disc Configure Network @@ -3663,6 +3664,7 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st - Server is crashed! - Server is suspended. - Server is in an unknown state (int: [#!variable!state!#]). + ]]> @@ -3933,6 +3940,8 @@ We will try to proceed anyway. #!variable!error!# ==== + + diff --git a/tools/anvil-manage-server-system b/tools/anvil-manage-server-system index e68915e7..d1502c4a 100755 --- a/tools/anvil-manage-server-system +++ b/tools/anvil-manage-server-system @@ -271,12 +271,6 @@ sub manage_boot_menu my $new_definition = ""; my $in_os = 0; my $bootmenu_seen = 0; -=cut - - hvm - - -=cut foreach my $line (split/\n/, $anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); @@ -289,23 +283,14 @@ sub manage_boot_menu { if ($line =~ //) { - my $old_value = $1; - $bootmenu_seen = 1; + my $old_value = $1; + $bootmenu_seen = 1; + $line =~ s///; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_value => $old_value, bootmenu_seen => $bootmenu_seen, + line => $line, }}); - if ($old_value eq $anvil->data->{switches}{'boot-menu'}) - { - # Update not needed. - print "The boot menu is already: [".$anvil->data->{switches}{'boot-menu'}."], update not needed.\n"; - } - else - { - # Update is needed. - $line =~ s///; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { line => $line }}); - } } if ($line =~ /<\/os>/) { @@ -322,21 +307,13 @@ sub manage_boot_menu } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_definition => $new_definition }}); - my $difference = diff \$anvil->data->{servers}{server_uuid}{$server_uuid}{server_definition_xml}, \$new_definition, { STYLE => 'Unified' }; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference }}); - - if ($difference) - { - # Test parse it. - my $problem = $anvil->Server->parse_definition({ - debug => 2, - host => $short_host_name, - server => $server_name, - source => "test", - definition => $new_definition, - }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); - } + # Always call this, as a previous run may have only updated some definitions. + my $problem = $anvil->Server->update_definition({ + debug => 2, + server => $server_uuid, + new_definition_xml => $new_definition, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); } else { From f12e001ac2ff0d591d48906cfae6d60a7c047fac Mon Sep 17 00:00:00 2001 From: digimer Date: Thu, 5 Oct 2023 23:49:05 -0400 Subject: [PATCH 06/25] Finished Server->connect_to_virsh(). * Now, connecting to virsh can detect when still-open connections already exist. Signed-off-by: digimer --- Anvil/Tools/Server.pm | 144 ++++++++++++++++++++++++++++++++++++++++++ share/words.xml | 2 + 2 files changed, 146 insertions(+) diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index 528225ed..d5015647 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -16,6 +16,7 @@ my $THIS_FILE = "Server.pm"; ### Methods; # active_migrations # boot_virsh +# connect_to_virsh # count_servers # find # find_processes @@ -296,6 +297,149 @@ WHERE return($success); } +=head2 connect_to_libvirt + +This creates a connection to the libvirtd daemon on the target host. The connection to the host will be stored in: + +* libvirtd::::connection + +If the connection succeeds, C<< 0 >> will be returned. If the connection fails, C<< 1 >> will be returned. + +parameters + +=head3 server_name (optional) + +If this is set to the name of a server, that server will be searched for and, if found, the handle to it will be stored in: + +* libvirtd::::server::::connection + +If the server is not found, that will be set to C<< 0 >> + +=head3 target (optional, default is the local short host name) + +This is the target to connect to. + +B<< Note >>: Don't use C<< localhost >>! If you do, it will be changed to the short host name. This is because C<< localhost >> is converted to C<< ::1 >> which can cause connection problems. + +=cut +sub connect_to_libvirt +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Server->connect_to_libvirt()" }}); + + my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : ""; + my $target = defined $parameter->{target} ? $parameter->{target} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + server_name => $server_name, + target => $target, + }}); + + if ((not $target)or ($target eq "localhost")) + { + # Change to the short host name. + $target = $anvil->Get->short_host_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target => $target }}); + } + + # Does the handle already exist? + if ((exists $anvil->data->{libvirtd}{$target}) && (ref($anvil->data->{libvirtd}{$target}{connection}) eq "Sys::Virt")) + { + # Is this connection alive? + my $info = $anvil->data->{libvirtd}{$target}{connection}->get_node_info(); + if (ref($info) eq "HASH") + { + # No need to connect. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0814", variables => { target => $target }}); + } + else + { + # Stale connection. + $anvil->data->{libvirtd}{$target}{connection} = ""; + } + } + else + { + $anvil->data->{libvirtd}{$target}{connection} = ""; + } + + # If we don't have a connection, try to establish one now. + if (not $anvil->data->{libvirtd}{$target}{connection}) + { + my $uri = "qemu+ssh://".$target."/system"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uri => $uri }}); + + # Test connect + eval { $anvil->data->{libvirtd}{$target}{connection} = Sys::Virt->new(uri => $uri); }; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "libvirtd::${target}::connection" => $anvil->data->{libvirtd}{$target}{connection}, + }}); + if ($@) + { + # Throw an error, then clear the URI so that we just update the DB/on-disk definitions. + $anvil->data->{libvirtd}{$target}{connection} = 0; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0162", variables => { + host_name => $target, + uri => $uri, + error => $@, + }}); + return(1); + } + } + + if ($server_name) + { + if (ref($anvil->data->{libvirtd}{$target}{server}{$server_name}{connection}) eq "Sys::Virt::Domain") + { + # If this connection still valid? + my $uuid = $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection}->get_uuid_string(); + if ($uuid) + { + # We're good. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0815", variables => { server_name => $server_name }}); + return(0); + } + else + { + # Stale connection. + $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection} = ""; + } + } + else + { + $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection} = ""; + } + + my $domain = ""; + my @domains = $anvil->data->{libvirtd}{$target}{connection}->list_all_domains(); + foreach my $domain_handle (@domains) + { + my $this_server_name = $domain_handle->get_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + domain_handle => $domain_handle, + this_server_name => $this_server_name, + }}); + next if $this_server_name ne $server_name; + + $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection} = $domain_handle; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "libvirtd::${target}::server::${server_name}::connection" => $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection}, + }}); + last; + } + } + + my $return = 0; + if (($server_name) && (not $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection})) + { + # Didn't find the server + return(1) + } + + return(0); +} =head2 count_servers diff --git a/share/words.xml b/share/words.xml index f73f20b3..58dcb931 100644 --- a/share/words.xml +++ b/share/words.xml @@ -2621,6 +2621,8 @@ The file: [#!variable!file!#] needs to be updated. The difference is: - The host: [#!variable!host_name!#] is not configured, skipping it. The file: [#!variable!full_path!#] is in the database multiple times. This could be an artifact from peering Strikers. Selecting an entry to remove... Deleting the 'files' database entry for the file uuid: [#!variable!file_uuid!#]. + There is an existing a functioning connection to: [#!variable!target!#], no need to reconnect. + There is an existing a functioning connection to the server: [#!variable!server_name!#], no need to reconnect. The host name: [#!variable!target!#] does not resolve to an IP address. From 829ae546a2416c61b55f9f9f4db45528cd67412b Mon Sep 17 00:00:00 2001 From: digimer Date: Fri, 6 Oct 2023 22:40:08 -0400 Subject: [PATCH 07/25] Beginning work on new Server->locate() method to find servers across an Anvil! cluster. Signed-off-by: digimer --- Anvil/Tools/Server.pm | 194 ++++++++++++++++++++-- ocf/alteeve/server | 1 + scancore-agents/scan-cluster/scan-cluster | 1 + 3 files changed, 186 insertions(+), 10 deletions(-) diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index d5015647..3ef87853 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -18,14 +18,15 @@ my $THIS_FILE = "Server.pm"; # boot_virsh # connect_to_virsh # count_servers -# find +# find # To be replaced by Server->locate(); # find_processes # get_definition # get_runtime # get_status +# locate # map_network -# parse_definition # migrate_virsh +# parse_definition # shutdown_virsh # update_definition @@ -313,7 +314,9 @@ If this is set to the name of a server, that server will be searched for and, if * libvirtd::::server::::connection -If the server is not found, that will be set to C<< 0 >> +If the server is not found, that will be set to C<< 0 >>. + +B<< Note >>: This can be set to C<< all >> and all servers we can connect to will be stored. =head3 target (optional, default is the local short host name) @@ -321,6 +324,10 @@ This is the target to connect to. B<< Note >>: Don't use C<< localhost >>! If you do, it will be changed to the short host name. This is because C<< localhost >> is converted to C<< ::1 >> which can cause connection problems. +=head3 target_ip (optional) + +If this is set, when building the URI, this IP or host name is used to connect. This allows the hash to use the C<< target >> name separately. + =cut sub connect_to_libvirt { @@ -332,9 +339,11 @@ sub connect_to_libvirt my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : ""; my $target = defined $parameter->{target} ? $parameter->{target} : ""; + my $target_ip = defined $parameter->{target_ip} ? $parameter->{target_ip} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_name => $server_name, target => $target, + target_ip => $target_ip, }}); if ((not $target)or ($target eq "localhost")) @@ -344,6 +353,12 @@ sub connect_to_libvirt $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target => $target }}); } + if (not $target_ip) + { + $target_ip = $target; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target_ip => $target_ip }}); + } + # Does the handle already exist? if ((exists $anvil->data->{libvirtd}{$target}) && (ref($anvil->data->{libvirtd}{$target}{connection}) eq "Sys::Virt")) { @@ -368,7 +383,7 @@ sub connect_to_libvirt # If we don't have a connection, try to establish one now. if (not $anvil->data->{libvirtd}{$target}{connection}) { - my $uri = "qemu+ssh://".$target."/system"; + my $uri = "qemu+ssh://".$target_ip."/system"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uri => $uri }}); # Test connect @@ -389,7 +404,7 @@ sub connect_to_libvirt } } - if ($server_name) + if (($server_name) && ($server_name ne "all")) { if (ref($anvil->data->{libvirtd}{$target}{server}{$server_name}{connection}) eq "Sys::Virt::Domain") { @@ -411,7 +426,11 @@ sub connect_to_libvirt { $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection} = ""; } - + } + + # If we have a server name, or if it's 'all', connect. + if ($server_name) + { my $domain = ""; my @domains = $anvil->data->{libvirtd}{$target}{connection}->list_all_domains(); foreach my $domain_handle (@domains) @@ -421,7 +440,10 @@ sub connect_to_libvirt domain_handle => $domain_handle, this_server_name => $this_server_name, }}); - next if $this_server_name ne $server_name; + if (($server_name ne "all") && ($this_server_name ne $server_name)) + { + next; + } $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection} = $domain_handle; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { @@ -432,7 +454,7 @@ sub connect_to_libvirt } my $return = 0; - if (($server_name) && (not $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection})) + if (($server_name) && ($server_name ne "all") && (not $anvil->data->{libvirtd}{$target}{server}{$server_name}{connection})) { # Didn't find the server return(1) @@ -508,6 +530,7 @@ pmsuspended - The domain has been suspended by guest power management, e.g. ente } +### TODO: Phase this out in favor for Server->locate() =head2 find This will look on the local or a remote machine for the list of servers that are running. @@ -1132,8 +1155,7 @@ sub map_network target => $target, }}); - # NOTE: We don't use 'Server->find' as the hassle of tracking hosts to target isn't worth it. - # Get a list of servers. + ### TODO: Switch to using Server->locate() my $shell_call = $anvil->data->{path}{exe}{setsid}." --wait ".$anvil->data->{path}{exe}{virsh}." list"; my $output = ""; if ($anvil->Network->is_local({host => $target})) @@ -1206,6 +1228,158 @@ sub map_network } +=head2 locate + +B<< Note >>: This is meant to replace C<< Server->find >> and so the hash conflicts. + +This walks through all known and accessible subnodes and DR hosts looking for a server. If it's found, it's status on that host are stored in the hash; + +* server_location::host::::access = [0,1] +* server_location::host::::server::::status = +* server_location::host::::server::::active_definition = +* server_location::host::::server::::inactive_definition = + +If the target was not accessible, C<< access >> is set to C<< 0 >>. This is meant to allow telling the difference between "we know there's no servers on that host" versus "we don't know what's there because we couldn't access it". + +If the server is found to be C<< unknown >> or C<< shut off >>, then C<< inactive_definition >> is not set. In all other states, the inactive XML is stored, but often it's the same as the C<< active_definition >>, so the caller is suggested to diff the XMLs when it might be relevant. + +The C<< status >> can be: + +* unknown # The server was found, but it has an unknown state +* running # Server is running. +* blocked # Server is blocked (IO contention?). +* paused # Server is paused (migration target?). +* in shutdown # Server is shutting down. +* shut off # Server is shut off. +* crashed # Server is crashed! +* pmsuspended # Server is suspended. + +If there is a problem, C<< !!error!! >> is returned. If the server is found on at least one host, C<< 0 >> is returned. If the server is not located anywhere, C<< 1 >> is returned. + +C<< Note >>: By design, servers are set to 'undefined' on subnodes, so when the server shuts off, it disappears from libvirtd. This is normal and expected. + +Parameters; + +=head3 server_name (required) + +This is the name of the server being located. It can be set to C<< all >>, in which case all servers on all hosts are located. + +=cut +sub locate +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Server->locate()" }}); + + my $server = defined $parameter->{server} ? $parameter->{server} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + server => $server, + }}); + + if (not $server) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->locate()", parameter => "server" }}); + return(1); + } + + if (exists $anvil->data->{server_location}{host}) + { + delete $anvil->data->{server_location}{host}; + } + + # Connect to all hosts. + $anvil->Database->get_hosts({debug => $debug}); + + foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}}) + { + my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name}; + my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; + my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name} + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:host_name' => $host_name, + 's2:host_uuid' => $host_uuid, + 's3:host_type' => $host_type, + 's4:short_host_name' => $short_host_name, + }}); + next if $host_type eq "striker"; + + # This will switch to '1' if we connect to libvirtd. + $anvil->data->{server_location}{host}{$short_host_name}{access} = 0; + + # What IP to use? + my $target_ip = $anvil->Network->find_target_ip({ + debug => $debug, + host_uuid => $host_uuid, + networks => "bcn,ifn", # Reduced list to not slow things down with test_access + test_access => 1, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target_ip => $target_ip }}); + + if ($target_ip) + { + # Try to connect to libvirtd. + my $problem = $anvil->Server->connect_to_libvirt({ + debug => $debug, + target => $short_host_name, + target_ip => $target_ip, + server => $server eq "all" ? "" : $server, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); + if (not $problem) + { + # We're connected! If we had a specific server + $anvil->data->{libvirtd}{$short_host_name}{connection} + } + + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{status} = ""; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{active_definition} = ""; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{inactive_definition} = ""; + + } + } + + + # Get the inactive XML (changes requested by the user may not match the in-memory XML) + my $virsh_definition_active = $anvil->data->{domain}{$server_name}{handle}->get_xml_description(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { virsh_definition_active => $virsh_definition_active }}); + + my $virsh_definition_inactive = $anvil->data->{domain}{$server_name}{handle}->get_xml_description(Sys::Virt::Domain::XML_INACTIVE); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virsh_definition_inactive => $virsh_definition_inactive }}); + + my ($anvil, $server_name) = @_; + + ### States: + # 0 = no state + # 1 = running - The domain is currently running on a CPU + # 2 = blocked (idle) - the domain is blocked on resource. This can be caused because the domain is waiting on IO (a traditional wait state) or has gone to sleep because there was nothing else for it to do. + # 3 = paused - The domain has been paused, usually occurring through the administrator running virsh suspend. When in a paused state the domain will still consume allocated resources like memory, but will not be eligible for scheduling by the hypervisor. + # 4 = in shutdown - The domain is in the process of shutting down, i.e. the guest operating system has been notified and should be in the process of stopping its operations gracefully. + # 5 = shut off - The domain is not running. Usually this indicates the domain has been shut down completely, or has not been started. + # 6 = crashed - The domain has crashed, which is always a violent ending. Usually this state can only occur if the domain has been configured not to restart on crash. + # 7 = pmsuspended - The domain has been suspended by guest power management, e.g. entered into s3 state. + my ($state, $reason) = $anvil->data->{domain}{$server_name}{handle}->get_state(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'state' => $state, + reason => $reason, + }}); + + ### Reasons are dependent on the state. + ### See: https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainShutdownReason + my $server_state = "unknown"; + if ($state == 1) { $server_state = "running"; } # Server is running. + elsif ($state == 2) { $server_state = "blocked"; } # Server is blocked (IO contention?). + elsif ($state == 3) { $server_state = "paused"; } # Server is paused (migration target?). + elsif ($state == 4) { $server_state = "in shutdown"; } # Server is shutting down. + elsif ($state == 5) { $server_state = "shut off"; } # Server is shut off. + elsif ($state == 6) { $server_state = "crashed"; } # Server is crashed! + elsif ($state == 7) { $server_state = "pmsuspended"; } # Server is suspended. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_state => $server_state }}); + + return($server_state); +} + =head2 migrate_virsh This will migrate (push or pull) a server from one node to another. If the migration was successful, C<< 1 >> is returned. Otherwise, C<< 0 >> is returned with a (hopefully) useful error being logged. diff --git a/ocf/alteeve/server b/ocf/alteeve/server index c8ef3978..acdccb05 100755 --- a/ocf/alteeve/server +++ b/ocf/alteeve/server @@ -1080,6 +1080,7 @@ sub start_drbd_resource return(0); } +### TODO: Rework this to use Server->connect_to_libvirtd and phase out Server->find(). # This uses the DRBD information to find other peers and see if the server is running on them. sub find_server { diff --git a/scancore-agents/scan-cluster/scan-cluster b/scancore-agents/scan-cluster/scan-cluster index 3d92ed4f..dac1623c 100755 --- a/scancore-agents/scan-cluster/scan-cluster +++ b/scancore-agents/scan-cluster/scan-cluster @@ -205,6 +205,7 @@ sub cib_cleanup return(0); } +### TODO: Rework this to use Server->connect_to_libvirtd and phase out Server->find(). # This looks for failed resource and, if found, tries to recover them. sub check_resources { From 55b1380031e2149758328688eb0fa01bd6fc2a80 Mon Sep 17 00:00:00 2001 From: digimer Date: Tue, 10 Oct 2023 19:14:00 -0400 Subject: [PATCH 08/25] Finished (but need more testing) of Server->locate(). This includes the changes in PR#492. Signed-off-by: digimer --- Anvil/Tools/Server.pm | 151 +++++++++++++++++++++++++---------------- share/words.xml | 1 + tools/anvil-join-anvil | 10 ++- 3 files changed, 103 insertions(+), 59 deletions(-) diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index 3ef87853..aa134fde 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -1230,18 +1230,21 @@ sub map_network =head2 locate -B<< Note >>: This is meant to replace C<< Server->find >> and so the hash conflicts. +B<< Note >>: This is meant to replace C<< Server->find >>. -This walks through all known and accessible subnodes and DR hosts looking for a server. If it's found, it's status on that host are stored in the hash; +This walks through all known and accessible subnodes and DR hosts looking for a server. If a specific server is searched for and it's found running, the C<< short_host_name >> is returned. If there is a problem, C<< !!error!! >> is returned. + +If a specific requested server is found, or is being asked to search for all servers, the following data is stored; * server_location::host::::access = [0,1] * server_location::host::::server::::status = * server_location::host::::server::::active_definition = * server_location::host::::server::::inactive_definition = +* server_location::host::::server::::definition_diff = If the target was not accessible, C<< access >> is set to C<< 0 >>. This is meant to allow telling the difference between "we know there's no servers on that host" versus "we don't know what's there because we couldn't access it". -If the server is found to be C<< unknown >> or C<< shut off >>, then C<< inactive_definition >> is not set. In all other states, the inactive XML is stored, but often it's the same as the C<< active_definition >>, so the caller is suggested to diff the XMLs when it might be relevant. +If the server is found to be C<< running >> or C<< paused >>, then C<< active_definition >> is set and, if there's a difference, that will be stored. In all other states, the inactive XML is stored. The C<< status >> can be: @@ -1256,6 +1259,11 @@ The C<< status >> can be: If there is a problem, C<< !!error!! >> is returned. If the server is found on at least one host, C<< 0 >> is returned. If the server is not located anywhere, C<< 1 >> is returned. +The connection to the host and to the server(s) is cached, for your use; + +* server_location::host::::connection = +* server_location::host::::server::::connection = + C<< Note >>: By design, servers are set to 'undefined' on subnodes, so when the server shuts off, it disappears from libvirtd. This is normal and expected. Parameters; @@ -1273,15 +1281,15 @@ sub locate my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "Server->locate()" }}); - my $server = defined $parameter->{server} ? $parameter->{server} : ""; + my $server_name = defined $parameter->{server_name} ? $parameter->{server_name} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - server => $server, + server_name => $server_name, }}); - if (not $server) + if (not $server_name) { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->locate()", parameter => "server" }}); - return(1); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Server->locate()", parameter => "server_name" }}); + return('!!error!!'); } if (exists $anvil->data->{server_location}{host}) @@ -1289,6 +1297,9 @@ sub locate delete $anvil->data->{server_location}{host}; } + # This will be set if the server is found to be 'running' on a host. + my $server_host = ""; + # Connect to all hosts. $anvil->Database->get_hosts({debug => $debug}); @@ -1296,7 +1307,7 @@ sub locate { my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name}; my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_type}; - my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name} + my $short_host_name = $anvil->data->{hosts}{host_uuid}{$host_uuid}{short_host_name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 's1:host_name' => $host_name, 's2:host_uuid' => $host_uuid, @@ -1321,63 +1332,87 @@ sub locate { # Try to connect to libvirtd. my $problem = $anvil->Server->connect_to_libvirt({ - debug => $debug, - target => $short_host_name, - target_ip => $target_ip, - server => $server eq "all" ? "" : $server, + debug => $debug, + target => $short_host_name, + target_ip => $target_ip, + server_name => $server_name, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); if (not $problem) { - # We're connected! If we had a specific server - $anvil->data->{libvirtd}{$short_host_name}{connection} + # We're connected! Collect the data on the requested server(s), if applicable. + $anvil->data->{server_location}{host}{$short_host_name}{access} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "server_location::host::${short_host_name}::access" => $anvil->data->{server_location}{host}{$short_host_name}{access}, + }}); + + if ($server_name) + { + my $connection_handle = $anvil->data->{libvirtd}{$short_host_name}{connection}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { connection_handle => $connection_handle }}); + foreach my $this_server_name (sort {$a cmp $b} keys %{$anvil->data->{libvirtd}{$short_host_name}{server}}) + { + if (($server_name eq "all") or ($server_name eq $this_server_name)) + { + my $server_handle = $anvil->data->{libvirtd}{$short_host_name}{server}{$server_name}{connection}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_handle => $server_handle }}); + + # Get the server's state, then convert to a string + my ($state, $reason) = $server_handle->get_state(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 'state' => $state, + reason => $reason, + }}); + + ### Reasons are dependent on the state. + ### See: https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainShutdownReason + my $server_state = "unknown"; + if ($state == 1) { $server_state = "running"; } # Server is running. + elsif ($state == 2) { $server_state = "blocked"; } # Server is blocked (IO contention?). + elsif ($state == 3) { $server_state = "paused"; } # Server is paused (migration target?). + elsif ($state == 4) { $server_state = "in shutdown"; } # Server is shutting down. + elsif ($state == 5) { $server_state = "shut off"; } # Server is shut off. + elsif ($state == 6) { $server_state = "crashed"; } # Server is crashed! + elsif ($state == 7) { $server_state = "pmsuspended"; } # Server is suspended. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_state => $server_state }}); + + # Get the persistent definition + my $inactive_definition = $server_handle->get_xml_description(Sys::Virt::Domain::XML_INACTIVE); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { inactive_definition => $inactive_definition }}); + + # Get the active definition, if applicable. + my $active_definition = ""; + my $definition_diff = ""; + if (($server_state eq "running") or ($server_state eq "paused")) + { + # Get the active definition + $active_definition = $server_handle->get_xml_description(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { active_definition => $active_definition }}); + + # Check for a diff. + $definition_diff = diff \$active_definition, \$inactive_definition, { STYLE => 'Unified' }; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { definition_diff => $definition_diff }}); + } + + # If it's running, record the host. + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{status} = $server_state; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{active_definition} = $active_definition; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{inactive_definition} = $inactive_definition; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{definition_diff} = $definition_diff; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "server_location::host::${short_host_name}::server::${server_name}::status" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{status}, + "server_location::host::${short_host_name}::server::${server_name}::active_definition" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{active_definition}, + "server_location::host::${short_host_name}::server::${server_name}::inactive_definition" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{inactive_definition}, + "server_location::host::${short_host_name}::server::${server_name}::definition_diff" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{definition_diff}, + }}); + } + } + } } - - $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{status} = ""; - $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{active_definition} = ""; - $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{inactive_definition} = ""; - } } - - # Get the inactive XML (changes requested by the user may not match the in-memory XML) - my $virsh_definition_active = $anvil->data->{domain}{$server_name}{handle}->get_xml_description(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { virsh_definition_active => $virsh_definition_active }}); - - my $virsh_definition_inactive = $anvil->data->{domain}{$server_name}{handle}->get_xml_description(Sys::Virt::Domain::XML_INACTIVE); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { virsh_definition_inactive => $virsh_definition_inactive }}); - - my ($anvil, $server_name) = @_; - - ### States: - # 0 = no state - # 1 = running - The domain is currently running on a CPU - # 2 = blocked (idle) - the domain is blocked on resource. This can be caused because the domain is waiting on IO (a traditional wait state) or has gone to sleep because there was nothing else for it to do. - # 3 = paused - The domain has been paused, usually occurring through the administrator running virsh suspend. When in a paused state the domain will still consume allocated resources like memory, but will not be eligible for scheduling by the hypervisor. - # 4 = in shutdown - The domain is in the process of shutting down, i.e. the guest operating system has been notified and should be in the process of stopping its operations gracefully. - # 5 = shut off - The domain is not running. Usually this indicates the domain has been shut down completely, or has not been started. - # 6 = crashed - The domain has crashed, which is always a violent ending. Usually this state can only occur if the domain has been configured not to restart on crash. - # 7 = pmsuspended - The domain has been suspended by guest power management, e.g. entered into s3 state. - my ($state, $reason) = $anvil->data->{domain}{$server_name}{handle}->get_state(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 'state' => $state, - reason => $reason, - }}); - - ### Reasons are dependent on the state. - ### See: https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainShutdownReason - my $server_state = "unknown"; - if ($state == 1) { $server_state = "running"; } # Server is running. - elsif ($state == 2) { $server_state = "blocked"; } # Server is blocked (IO contention?). - elsif ($state == 3) { $server_state = "paused"; } # Server is paused (migration target?). - elsif ($state == 4) { $server_state = "in shutdown"; } # Server is shutting down. - elsif ($state == 5) { $server_state = "shut off"; } # Server is shut off. - elsif ($state == 6) { $server_state = "crashed"; } # Server is crashed! - elsif ($state == 7) { $server_state = "pmsuspended"; } # Server is suspended. - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_state => $server_state }}); - - return($server_state); + return($server_host); } =head2 migrate_virsh diff --git a/share/words.xml b/share/words.xml index 58dcb931..c40d8099 100644 --- a/share/words.xml +++ b/share/words.xml @@ -2623,6 +2623,7 @@ The file: [#!variable!file!#] needs to be updated. The difference is: Deleting the 'files' database entry for the file uuid: [#!variable!file_uuid!#]. There is an existing a functioning connection to: [#!variable!target!#], no need to reconnect. There is an existing a functioning connection to the server: [#!variable!server_name!#], no need to reconnect. + Waiting for: [#!variable!delay!#] seconds. The host name: [#!variable!target!#] does not resolve to an IP address. diff --git a/tools/anvil-join-anvil b/tools/anvil-join-anvil index 5451acfd..17fa14ea 100755 --- a/tools/anvil-join-anvil +++ b/tools/anvil-join-anvil @@ -298,6 +298,9 @@ sub configure_pacemaker my $both_online = 0; until($both_online) { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + 'path::configs::corosync.conf' => $anvil->data->{path}{configs}{'corosync.conf'}, + }}); if (-e $anvil->data->{path}{configs}{'corosync.conf'}) { if (not $start_time) @@ -362,7 +365,12 @@ sub configure_pacemaker # corosync.conf doesn't exist yet. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0107"}); } - sleep 5 if not $both_online; + if (not $both_online) + { + my $delay = 5; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0816", variables => { delay => $delay }}); + sleep $delay; + } } } else From 68521cdab7dd91d1c56bed2a789a9d573276b44a Mon Sep 17 00:00:00 2001 From: digimer Date: Wed, 11 Oct 2023 17:19:39 -0400 Subject: [PATCH 09/25] Updated striker-get-screenshots to set permissions properly. This updates the /opt/alteeve/screenshot directories and the screenshots in them to be readible by the WebUI. Signed-off-by: digimer --- Anvil/Tools.pm | 1 + tools/anvil-join-anvil | 2 +- tools/striker-get-screenshots | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 6745afa2..0a37e938 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -1115,6 +1115,7 @@ sub _set_paths ifcfg => "/etc/sysconfig/network-scripts", journald => "/var/log/journal", libvirtd_definitions => "/etc/libvirt/qemu/", + opt_alteeve => "/opt/alteeve", pgsql => "/var/lib/pgsql/", resource_status => "/sys/kernel/debug/drbd/resources", scan_agents => "/usr/sbin/scancore-agents", diff --git a/tools/anvil-join-anvil b/tools/anvil-join-anvil index 17fa14ea..b6d9ad1b 100755 --- a/tools/anvil-join-anvil +++ b/tools/anvil-join-anvil @@ -298,7 +298,7 @@ sub configure_pacemaker my $both_online = 0; until($both_online) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'path::configs::corosync.conf' => $anvil->data->{path}{configs}{'corosync.conf'}, }}); if (-e $anvil->data->{path}{configs}{'corosync.conf'}) diff --git a/tools/striker-get-screenshots b/tools/striker-get-screenshots index 0805428e..28b8bc42 100755 --- a/tools/striker-get-screenshots +++ b/tools/striker-get-screenshots @@ -42,6 +42,9 @@ if ($anvil->data->{switches}{'job-uuid'}) $anvil->data->{job}{progress} = 1; +# Make sure the directory we write screenshots to exists and has the proper ownership and mode. +check_screenshot_directory($anvil); + # Which subnodes are up? $anvil->Database->get_hosts(); $anvil->Database->get_dr_links(); @@ -178,6 +181,29 @@ $anvil->nice_exit({exit_code => 0}); # Functions # ############################################################################################################# +sub check_screenshot_directory +{ + my ($anvil) = @_; + + foreach my $directory ($anvil->data->{path}{directories}{opt_alteeve}, $anvil->data->{path}{directories}{screenshots}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { directory => $directory }}); + $anvil->Storage->change_owner({ + debug => 2, + path => $directory, + user => "striker-ui-api", + group => "striker-ui-api", + }); + $anvil->Storage->change_mode({ + debug => 2, + path => $directory, + mode => "0755", + }); + } + + return(0); +} + sub remove_old_screenshots { my ($anvil) = @_; @@ -411,6 +437,14 @@ sub get_screenshots 'format' => "jpeg", }, }); + + # Change the ownership + $anvil->Storage->change_owner({ + debug => 2, + path => $jpg_file, + user => "striker-ui-api", + group => "striker-ui-api", + }); } # Convert to png @@ -438,6 +472,14 @@ sub get_screenshots 'format' => "png", }, }); + + # Change the ownership + $anvil->Storage->change_owner({ + debug => 2, + path => $png_file, + user => "striker-ui-api", + group => "striker-ui-api", + }); } # Delete the original PPM file? From 7545df1e555460a7f097c52a4bdad3c6585bcc4b Mon Sep 17 00:00:00 2001 From: digimer Date: Wed, 11 Oct 2023 22:22:06 -0400 Subject: [PATCH 10/25] Fixed a bug in which host runs an anvil-delete-server job. * Updated anvil-delete-server to use the new Server->locate method. This was done as the old Server->locate() was failing to find the server running on the peer when anvil-delete-server was running on the backup subnode. * Updated Server->locate() to search hosts for XML definition and DRBD configs so that it can record where the server is recorded to run, even if the server isn't running or defined at the time the locate ran. Signed-off-by: digimer --- Anvil/Tools/Server.pm | 94 ++++++++++++++++++++++++++++++++++++--- tools/anvil-delete-server | 80 ++++++++++++++++++--------------- 2 files changed, 132 insertions(+), 42 deletions(-) diff --git a/Anvil/Tools/Server.pm b/Anvil/Tools/Server.pm index aa134fde..2fbd30f9 100644 --- a/Anvil/Tools/Server.pm +++ b/Anvil/Tools/Server.pm @@ -1241,6 +1241,8 @@ If a specific requested server is found, or is being asked to search for all ser * server_location::host::::server::::active_definition = * server_location::host::::server::::inactive_definition = * server_location::host::::server::::definition_diff = +* server_location::host::::server::::file_definition = +* server_location::host::::server::::drbd_config = If the target was not accessible, C<< access >> is set to C<< 0 >>. This is meant to allow telling the difference between "we know there's no servers on that host" versus "we don't know what's there because we couldn't access it". @@ -1259,6 +1261,8 @@ The C<< status >> can be: If there is a problem, C<< !!error!! >> is returned. If the server is found on at least one host, C<< 0 >> is returned. If the server is not located anywhere, C<< 1 >> is returned. +If the server has a replicated storage (DRBD) config and/or a definition file, whether the server is found running or not, will be recorded. This can be used to see if the server has been configured to run there or not. + The connection to the host and to the server(s) is cached, for your use; * server_location::host::::connection = @@ -1319,26 +1323,28 @@ sub locate # This will switch to '1' if we connect to libvirtd. $anvil->data->{server_location}{host}{$short_host_name}{access} = 0; - # What IP to use? + # What IP to use? Don't test access, it's too slow if there's several down hosts. my $target_ip = $anvil->Network->find_target_ip({ debug => $debug, host_uuid => $host_uuid, - networks => "bcn,ifn", # Reduced list to not slow things down with test_access - test_access => 1, + networks => "bcn,mn,sn,ifn", + test_access => 0, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { target_ip => $target_ip }}); if ($target_ip) { # Try to connect to libvirtd. - my $problem = $anvil->Server->connect_to_libvirt({ + $anvil->Server->connect_to_libvirt({ debug => $debug, target => $short_host_name, target_ip => $target_ip, server_name => $server_name, }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { problem => $problem }}); - if (not $problem) + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "libvirtd::${short_host_name}::connection" => $anvil->data->{libvirtd}{$short_host_name}{connection}, + }}); + if (ref($anvil->data->{libvirtd}{$short_host_name}{connection}) eq "Sys::Virt") { # We're connected! Collect the data on the requested server(s), if applicable. $anvil->data->{server_location}{host}{$short_host_name}{access} = 1; @@ -1352,6 +1358,7 @@ sub locate $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { connection_handle => $connection_handle }}); foreach my $this_server_name (sort {$a cmp $b} keys %{$anvil->data->{libvirtd}{$short_host_name}{server}}) { + next if (ref($anvil->data->{libvirtd}{$short_host_name}{server}{$server_name}{connection}) ne "Sys::Virt::Domain"); if (($server_name eq "all") or ($server_name eq $this_server_name)) { my $server_handle = $anvil->data->{libvirtd}{$short_host_name}{server}{$server_name}{connection}; @@ -1394,6 +1401,12 @@ sub locate $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { definition_diff => $definition_diff }}); } + if ($server_state eq "running") + { + $server_host = $short_host_name; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { server_host => $server_host }}); + } + # If it's running, record the host. $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{status} = $server_state; $anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{active_definition} = $active_definition; @@ -1407,6 +1420,75 @@ sub locate }}); } } + + # If we've connected to the host, see if the XML definition file + # and/or DRBD config file exist. + my $servers = []; + if ($server_name eq "all") + { + # Search for any server we can find. + $anvil->Database->get_servers(); + foreach my $server_uuid (sort {$a cmp $b} keys %{$anvil->data->{servers}{server_uuid}}) + { + next if $anvil->data->{servers}{server_uuid}{$server_uuid}{server_state} eq "DELETED"; + my $this_server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + server_uuid => $server_uuid, + this_server_name => $this_server_name, + }}); + push @{$servers}, $this_server_name; + } + } + else + { + push @{$servers}, $server_name; + } + + foreach my $this_server_name (sort {$a cmp $b} @{$servers}) + { + # Look for the files for the specified server. + $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{file_definition} = ""; + $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{drbd_config} = ""; + + # See if there's a definition file and/or a DRBD + # config file on this host. + my $definition_file = $anvil->data->{path}{directories}{shared}{definitions}."/".$this_server_name.".xml"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { definition_file => $definition_file }}); + + # Can I read the definition file? + my $definition_body = $anvil->Storage->read_file({ + debug => $debug, + file => $definition_file, + target => $target_ip, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { definition_body => $definition_body }}); + + if (($definition_body) && ($definition_body ne "!!error!!")) + { + $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{file_definition} = $definition_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "server_location::host::${short_host_name}::server::${this_server_name}::file_definition" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{file_definition}, + }}); + } + + my $drbd_config_file = $anvil->data->{path}{directories}{drbd_resources}."/".$this_server_name.".res"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { drbd_config_file => $drbd_config_file }}); + + my $drbd_body = $anvil->Storage->read_file({ + debug => $debug, + file => $drbd_config_file, + target => $target_ip, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { drbd_body => $drbd_body }}); + if (($drbd_body) && ($drbd_body ne "!!error!!")) + { + $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{drbd_config} = $drbd_body; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "server_location::host::${short_host_name}::server::${this_server_name}::drbd_config" => $anvil->data->{server_location}{host}{$short_host_name}{server}{$this_server_name}{drbd_config}, + }}); + } + } } } } diff --git a/tools/anvil-delete-server b/tools/anvil-delete-server index e9fa2e03..4b7bdc89 100755 --- a/tools/anvil-delete-server +++ b/tools/anvil-delete-server @@ -774,58 +774,66 @@ sub save_job my $server_name = $anvil->data->{switches}{server_name}; my $server_uuid = $anvil->data->{switches}{server_uuid}; my $delete_uuid = $server_uuid; - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}; - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid}; - if ($anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}) + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + anvil_uuid => $anvil_uuid, + server_name => $server_name, + server_uuid => $server_uuid, + delete_uuid => $delete_uuid, + }}); + + if ((not $server_name) && (exists $anvil->data->{servers}{server_uuid}{$server_uuid}) && ($anvil->data->{servers}{server_uuid}{$server_uuid}{server_name})) { - push @{$hosts}, $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_dr1_host_uuid}; + $server_name = $anvil->data->{servers}{server_uuid}{$server_uuid}{server_name}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_name => $server_name }}); } - my $server_host = ""; - foreach my $host_uuid (@{$hosts}) + + # Find the server on hosts. + my $server_host_name = $anvil->Server->locate({ + debug => 2, + server_name => $server_name, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_name => $server_host_name }}); + + foreach my $short_host_name (sort {$a cmp $b} keys %{$anvil->data->{server_location}{host}}) { - if ($host_uuid eq $anvil->Get->host_uuid) + my $host_uuid = $anvil->Database->get_host_uuid_from_string({string => $short_host_name}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + short_host_name => $short_host_name, + host_uuid => $host_uuid, + }}); + + my $exists = 0; + if (($anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{file_definition}) or ($anvil->data->{server_location}{host}{$short_host_name}{server}{$server_name}{drbd_config})) { - # This is us. - $anvil->Server->find({refresh => 0}); + $exists = 1; } - else + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'exists' => $exists }}); + + if (($exists) or + ($host_uuid eq $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node1_host_uuid}) or + ($host_uuid eq $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{anvil_node2_host_uuid})) { - # This is another machine. - my $target_ip = $anvil->Network->find_target_ip({host_uuid => $host_uuid}); - $anvil->Server->find({ - refresh => 0, - target => $target_ip, - password => $password, - }); + push @{$hosts}, $host_uuid; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); } } - my $host_name = ""; - my $host_uuid = ""; - if (exists $anvil->data->{server}{location}{$server_name}) + # If the server was found to be running, the host will be returned. + my $server_host_uuid = ""; + if ($server_host_name) { - my $status = $anvil->data->{server}{location}{$server_name}{status}; - $host_name = $anvil->data->{server}{location}{$server_name}{host_name}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - status => $status, - host_name => $host_name, - }}); - if ($status eq "running") - { - $host_uuid = $anvil->Get->host_uuid_from_name({host_name => $host_name}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); - } + $server_host_uuid = $anvil->Get->host_uuid_from_name({host_name => $server_host_name}); } # Now, we'll do the delete, unless we see the server running elsewhere. - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { server_host_uuid => $server_host_uuid }}); my $job_host_uuid = ""; - if ($host_uuid) + if ($server_host_uuid) { - $job_host_uuid = $host_uuid; + $job_host_uuid = $server_host_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { job_host_uuid => $job_host_uuid }}); - if ($host_uuid eq $anvil->Get->host_uuid) + if ($server_host_uuid eq $anvil->Get->host_uuid) { # Running here print $anvil->Words->string({key => "message_0216"})."\n"; @@ -833,7 +841,7 @@ sub save_job else { # Running on a peer. - print $anvil->Words->string({key => "message_0214", variables => { host_name => $host_name }})."\n"; + print $anvil->Words->string({key => "message_0214", variables => { host_name => $server_host_name }})."\n"; } } else From b3c067b0165d14d989b3d365d96fbeffb2455b17 Mon Sep 17 00:00:00 2001 From: digimer Date: Thu, 12 Oct 2023 01:01:31 -0400 Subject: [PATCH 11/25] Fixed a bug in anvil-manage-files where missing files weren't being downloaded. Signed-off-by: digimer --- Anvil/Tools/Database.pm | 2 +- Anvil/Tools/Storage.pm | 2 +- tools/anvil-manage-files | 14 ++++---------- tools/striker-file-manager | 2 ++ 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index dade1c1d..5e33a51e 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -3580,7 +3580,7 @@ FROM }}); } - # If this host is a node in an Anvil!, set the old 'file_location_anvil_uuid' to maintain + # If this host is an Anvil! subnode, set the old 'file_location_anvil_uuid' to maintain # backwards compatibility. if ((exists $anvil->data->{hosts}{host_uuid}{$file_location_host_uuid}) && ($anvil->data->{hosts}{host_uuid}{$file_location_host_uuid}{anvil_uuid})) diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm index 40fc9d82..053e8e32 100644 --- a/Anvil/Tools/Storage.pm +++ b/Anvil/Tools/Storage.pm @@ -776,7 +776,7 @@ sub check_files } elsif ($file_location_ready) { - # File doesn't exist but is marked as read, mark it as not ready. + # File doesn't exist but is marked as ready, mark it as not ready. $anvil->Database->insert_or_update_file_locations({ debug => $debug, file_location_uuid => $file_location_uuid, diff --git a/tools/anvil-manage-files b/tools/anvil-manage-files index db915c3f..075ddb19 100755 --- a/tools/anvil-manage-files +++ b/tools/anvil-manage-files @@ -175,6 +175,9 @@ sub find_missing_files # What am I? This will impact how missing files are found. $anvil->Database->get_anvils(); + my $host_uuid = $anvil->Get->host_uuid(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }}); + my $query = " SELECT file_uuid, @@ -237,16 +240,7 @@ ORDER BY else { # Check to see if we're supposed to have this file. - $anvil->Database->get_file_locations(); - my $anvil_uuid = $anvil->Cluster->get_anvil_uuid(); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); - - # Nothing to do if we're not in an Anvil! yet. - next if not $anvil_uuid; - - # Do we have a file_location_uuid? If not, there will be soon but nothing to do until - # then. - my $file_location_uuid = $anvil->data->{anvils}{anvil_uuid}{$anvil_uuid}{file_uuid}{$file_uuid}{file_location_uuid}; + my $file_location_uuid = $anvil->data->{file_locations}{host_uuid}{$host_uuid}{file_uuid}{$file_uuid}{file_location_uuid}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_location_uuid => $file_location_uuid }}); next if not $file_location_uuid; diff --git a/tools/striker-file-manager b/tools/striker-file-manager index aed0d50c..78256c41 100755 --- a/tools/striker-file-manager +++ b/tools/striker-file-manager @@ -2,6 +2,8 @@ # # This is the command line user interface for managing files on /mnt/shared/files on Strikers and made # available on Anvil! systems. +# +# NOTE: This program is incomplete! # use strict; From 4398ffe70c1979da603ee045f8c76e8e87b15f19 Mon Sep 17 00:00:00 2001 From: digimer Date: Thu, 12 Oct 2023 22:15:41 -0400 Subject: [PATCH 12/25] Updated striker-boot-machine to support booting all machines. * Wrote the man page for striker-boot-machine, changing --host-name to --host, and adding the '--host all' support. * Updated anvil-manage-host to support checking/enabling/disabling network mapping mode. Signed-off-by: digimer --- cgi-bin/set_power | 2 +- man/anvil-manage-host.8 | 57 ++++++++++ man/striker-boot-machine.8 | 38 +++++++ share/words.xml | 4 + tools/anvil-manage-host | 117 ++++++++++++++++++- tools/striker-boot-machine | 225 +++++++++++++++++++++++-------------- 6 files changed, 354 insertions(+), 89 deletions(-) diff --git a/cgi-bin/set_power b/cgi-bin/set_power index e49129ac..536fbb7d 100755 --- a/cgi-bin/set_power +++ b/cgi-bin/set_power @@ -107,7 +107,7 @@ sub set_host_power elsif (not $is_host_on && $on) { $anvil->Database->insert_or_update_jobs({ - job_command => $anvil->data->{path}{directories}{tools}."/striker-boot-machine --host-uuid ".$host_uuid, + job_command => $anvil->data->{path}{directories}{tools}."/striker-boot-machine --host ".$host_uuid, job_description => "job_0335", job_name => "cgi-bin::set_power::on", job_progress => 0, diff --git a/man/anvil-manage-host.8 b/man/anvil-manage-host.8 index e69de29b..f6dbf9d8 100644 --- a/man/anvil-manage-host.8 +++ b/man/anvil-manage-host.8 @@ -0,0 +1,57 @@ +.\" Manpage for the Anvil! server boot program +.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. +.TH anvil-manage-host "8" "Octobober 12 2023" "Anvil! Intelligent Availability™ Platform" +.SH NAME +anvil-manage-host \- Tool used to check or set various configuration options for a host. +.SH SYNOPSIS +.B anvil-manage-host +\fI\, \/\fR[\fI\,options\/\fR] +.SH DESCRIPTION + +.TP +.SH OPTIONS +.TP +\-?, \-h, \fB\-\-help\fR +Show this man page. +.TP +\fB\-\-log-secure\fR +When logging, record sensitive data, like passwords. +.TP +\-v, \-vv, \-vvv +Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data. +.SS "Commands:" +.TP +\fB\-\-age\-out\-database\fR +This requests the database check for records that are too old and purge them. +.TP +\fB\-\-check\-configured\fR +Check to see if the host is marked as configured or yet. +.TP +\fB\-\-check\-database\fR +This checks to see if the database is enabled or not. +.TP +\fB\-\-check\-network\-mapping\fR +This reports if the host is currently in network mapping (this disables several features and watches the network states much more frequently) +.TP +\fB\-\-database\-active\fR +This enables the database on the local Striker dashboard. +.TP +\fB\-\-database\-inactive\fR +This disables the database on the local Striker dashboard. +.TP +\fB\-\-disable\-network\-mapping\fR +This disables the network mapping mode. +.TP +\fB\-\-enable\-network\-mapping\fR +This enables the network mapping mode. +.TP +\fB\-\-mark\-configured\fR +This marks the host as having been configured. +.TP +\fB\-\-resync\-database\fR +This forces a database resync if two or more strikers are online. +.IP +.SH AUTHOR +Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. +.SH "REPORTING BUGS" +Report bugs to users@clusterlabs.org diff --git a/man/striker-boot-machine.8 b/man/striker-boot-machine.8 index e69de29b..1393aac3 100644 --- a/man/striker-boot-machine.8 +++ b/man/striker-boot-machine.8 @@ -0,0 +1,38 @@ +.\" Manpage for the Anvil! server boot program +.\" Contact mkelly@alteeve.com to report issues, concerns or suggestions. +.TH striker-boot-machine "8" "Octobober 12 2023" "Anvil! Intelligent Availability™ Platform" +.SH NAME +striker-boot-machine \- Tool used to boot physical machines that have IPMI configuration information. +.SH SYNOPSIS +.B striker-boot-machine +\fI\, \/\fR[\fI\,options\/\fR] +.SH DESCRIPTION +This tool is used to power up any machine in the cluster with IPMI configuration in the database. Typically this is subnodes and DR hosts, but could also be Striker dashboards if they have an IPMI BMC. If the server is found to already be om, it will NOT be booted again. +.TP +.SH OPTIONS +.TP +\-?, \-h, \fB\-\-help\fR +Show this man page. +.TP +\fB\-\-log-secure\fR +When logging, record sensitive data, like passwords. +.TP +\-v, \-vv, \-vvv +Set the log level to 1, 2 or 3 respectively. Be aware that level 3 generates a significant amount of log data. +.SS "Commands:" +.TP +\fB\-\-host\fR +This is the host name or UUID of the server to power on. If this is set to 'all', all machines that have IPMI configuration information will be checked, and if it's found to be off, it will be booted. +.TP +\fB\-\-host-uuid\fR +This is effectively the same as \fB\-\-host\fR, but provides backwards compatibility. It's use is discouraged. +.TP +\fB\-\-job\-uuid\fR +If this is set, the job will be processed. +.TP +Be aware that when this is used, if a server fails to boot, no further servers will be started. +.IP +.SH AUTHOR +Written by Madison Kelly, Alteeve staff and the Anvil! project contributors. +.SH "REPORTING BUGS" +Report bugs to users@clusterlabs.org diff --git a/share/words.xml b/share/words.xml index c40d8099..83f46d16 100644 --- a/share/words.xml +++ b/share/words.xml @@ -3172,6 +3172,10 @@ Proceed? [y/N] Preparing to managing storage for a server. Running checks before processing power request... The job to: [#!variable!task!#] this host has been picked up. + This host is already configured to map the network. + This host is now configured to map the network. + This host is already NOT configured to map the network. + This host is no longer configured to map the network. Normal Password diff --git a/tools/anvil-manage-host b/tools/anvil-manage-host index 28f37a86..0a45bb56 100755 --- a/tools/anvil-manage-host +++ b/tools/anvil-manage-host @@ -28,8 +28,11 @@ $anvil->Get->switches({list => [ "age-out-database", "check-configured", "check-database", + "check-network-mapping", "database-active", "database-inactive", + "disable-network-mapping", + "enable-network-mapping", "mark-configured", "mark-unconfigured", "resync-database"], man => $THIS_FILE}); @@ -53,6 +56,10 @@ elsif (($anvil->data->{switches}{'database-active'}) or ($anvil->data->{switches { update_database($anvil); } +elsif (($anvil->data->{switches}{'enable-network-mapping'}) or ($anvil->data->{switches}{'disable-network-mapping'}) or ($anvil->data->{switches}{'check-network-mapping'})) +{ + update_network_mapping($anvil); +} elsif ($anvil->data->{switches}{'age-out-database'}) { age_out_data($anvil); @@ -156,7 +163,6 @@ sub update_database variable_name => $variable_name, }}); - # Read if it's active or inactive yet. my ($active_value, undef, undef) = $anvil->Database->read_variable({variable_name => "database::".$host_uuid."::active"}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { active_value => $active_value }}); @@ -224,6 +230,114 @@ sub update_database return(0); } +sub update_network_mapping +{ + my ($anvil) = @_; + + my $variable_name = "config::map_network"; + my ($map_network_value, $map_network_uuid, $map_network_mtime, $map_network_modified_date) = $anvil->Database->read_variable({ + variable_name => $variable_name, + variable_source_table => "hosts", + variable_source_uuid => $anvil->data->{sys}{host_uuid}, + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:variable_name' => $variable_name, + 's2:map_network_value' => $map_network_value, + 's3:map_network_mtime' => $map_network_mtime, + 's4:map_network_modified_date' => $map_network_modified_date, + 's5:map_network_uuid' => $map_network_uuid, + }}); + if ($anvil->data->{switches}{'check-configured'}) + { + # We'll run for a day (should be cancelled by the program when the user's done, so this + # shouldn't fire in practice). + my $expire_age = 86400; + my $map_network_age = 0; + if ($map_network_uuid) + { + $map_network_age = time - $map_network_mtime; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { map_network_age => $map_network_age }}); + } + if ($map_network_value) + { + # How long ago was it set? + $anvil->data->{switches}{'clear-mapping'} = "" if not defined $anvil->data->{switches}{'clear-mapping'}; + if (($map_network_age >= $expire_age) or ($anvil->data->{switches}{'clear-mapping'})) + { + # Clear it. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "log_0470"}); + $anvil->Database->insert_or_update_variables({ + debug => 3, + variable_value => 0, + variable_uuid => $map_network_uuid, + update_value_only => 1, + }); + } + else + { + # Mark it so we only track the network. + my $say_age = $anvil->Convert->add_commas({number => $expire_age}); + my $timeout = $anvil->Convert->add_commas({number => ($expire_age - $map_network_age)}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0471", variables => { + age => $say_age, + timeout => $timeout, + }}); + } + } + return(0); + } + + if ($anvil->data->{switches}{'enable-network-mapping'}) + { + if ($map_network_value) + { + # Nothing to do. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0353"}); + } + else + { + # Enable network configuring. + my $variable_uuid = $anvil->Database->insert_or_update_variables({ + variable_name => $variable_name, + variable_value => 1, + variable_default => "", + variable_description => "striker_0202", + variable_section => "config", + variable_source_uuid => $anvil->Get->host_uuid, + variable_source_table => "hosts", + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0354"}); + } + } + + if ($anvil->data->{switches}{'disable-network-mapping'}) + { + if ($map_network_value) + { + # Disable network configuring. + my $variable_uuid = $anvil->Database->insert_or_update_variables({ + variable_name => $variable_name, + variable_value => 0, + variable_default => "", + variable_description => "striker_0202", + variable_section => "config", + variable_source_uuid => $anvil->Get->host_uuid, + variable_source_table => "hosts", + }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0356"}); + } + else + { + # Nothing to do. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0355"}); + } + } + + return(0); +} + sub update_config { my ($anvil) = @_; @@ -292,6 +406,5 @@ sub update_config } } - return(0); } diff --git a/tools/striker-boot-machine b/tools/striker-boot-machine index d9ef51b6..8a99e5ff 100755 --- a/tools/striker-boot-machine +++ b/tools/striker-boot-machine @@ -26,16 +26,12 @@ $| = 1; my $anvil = Anvil::Tools->new(); -$anvil->data->{switches}{'job-uuid'} = ""; -$anvil->data->{switches}{'host-uuid'} = ""; -$anvil->data->{switches}{'host-name'} = ""; -$anvil->Get->switches; -$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); -$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 'switches::job-uuid' => $anvil->data->{switches}{'job-uuid'}, - 'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'}, - 'switches::host-name' => $anvil->data->{switches}{'host-name'}, -}}); +$anvil->Get->switches({list => [ + "host", + "host-uuid", + "job-uuid"], man => $THIS_FILE}); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); +$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); $anvil->Database->connect(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, secure => 0, key => "log_0132"}); @@ -70,23 +66,34 @@ if ($anvil->data->{switches}{'job-uuid'}) 'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'}, }}); } - if ($line =~ /host-name=(.*?)$/) + if ($line =~ /host=(.*?)$/) { - $anvil->data->{switches}{'host-name'} = $1; + $anvil->data->{switches}{host} = $1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - 'switches::host-name' => $anvil->data->{switches}{'host-name'}, + 'switches::host' => $anvil->data->{switches}{host}, }}); } } } -# If we have a host name, but not a host-uuid, look up the host UUID. -if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{'host-name'})) +# Get the host info (copy host-uuid to host) +$anvil->data->{switches}{'host-name'} = "" if not defined $anvil->data->{switches}{'host-name'}; +if ((not $anvil->data->{switches}{host}) && ($anvil->data->{switches}{'host-uuid'})) { - $anvil->data->{switches}{'host-uuid'} = $anvil->Get->host_uuid_from_name({host_name => $anvil->data->{switches}{'host-name'}}); + $anvil->data->{switches}{host} = $anvil->data->{switches}{'host-uuid'}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'switches::host' => $anvil->data->{switches}{host}, + }}); +} + +# If the host is 'all', don't translate to the host_uuid. Otherwise, look for the host_uuid from the host string +if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{host} ne "all")) +{ + $anvil->data->{switches}{'host-uuid'} = $anvil->Database->get_host_uuid_from_string({string => $anvil->data->{switches}{host}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'switches::host-uuid' => $anvil->data->{switches}{'host-uuid'}, }}); + # host name not found if (not $anvil->data->{switches}{'host-uuid'}) { @@ -94,14 +101,11 @@ if ((not $anvil->data->{switches}{'host-uuid'}) && ($anvil->data->{switches}{'ho $anvil->Job->update_progress({progress => 100, message => "error_0291,!!host_name!".$anvil->data->{switches}{'host-name'}."!!"}); $anvil->nice_exit({exit_code => 1}); } -} - -# If we still don't have a host_uuid, we can't proceed. -if (not $anvil->data->{switches}{'host-uuid'}) -{ - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0290"}); - $anvil->Job->update_progress({progress => 100, message => "error_0290"}); - $anvil->nice_exit({exit_code => 1}); + + $anvil->data->{switches}{'host-name'} = $anvil->Get->host_name_from_uuid({host_uuid => $anvil->data->{switches}{'host-uuid'}}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 'switches::host-name' => $anvil->data->{switches}{'host-name'}, + }}); } find_boot_method($anvil); @@ -121,85 +125,134 @@ sub find_boot_method $anvil->Database->get_hosts_info({debug => 2}); - my $host_uuid = $anvil->data->{switches}{'host-uuid'}; - my $host_name = $anvil->data->{machine}{host_uuid}{$host_uuid}{hosts}{host_name}; - my $host_ipmi = $anvil->data->{machine}{host_uuid}{$host_uuid}{hosts}{host_ipmi}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - host_uuid => $host_uuid, - host_name => $host_name, - host_ipmi => $anvil->Log->is_secure($host_ipmi), - }}); - - $anvil->data->{sys}{progress} = 10; - - # If we have IPMI, that's the easiest method. - if ($host_ipmi) + my $hosts = []; + if ($anvil->data->{switches}{'host-uuid'}) { - # Got it. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "job_0327", variables => { host_name => $host_name }}); - $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}+=10, message => "job_0327,!!host_name!".$host_name."!!"}); - - # First, is the node already on? - my $shell_call = $host_ipmi." -o status"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { shell_call => $shell_call }}); - - call_fence_agent($anvil, $shell_call); + push @{$hosts}, $anvil->data->{switches}{'host-name'}; + } + elsif ($anvil->data->{switches}{host} eq "all") + { + $anvil->Database->get_hosts({debug => 2}); + foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{sys}{hosts}{by_name}}) + { + my $host_uuid = $anvil->data->{sys}{hosts}{by_name}{$host_name}; + my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}; + my $host_key = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_key}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + 's1:host_name' => $host_name, + 's2:host_uuid' => $host_uuid, + 's3:host_ipmi' => $anvil->Log->is_secure($host_ipmi), + }}); + next if $host_key eq "DELETED"; + next if not $host_ipmi; + + push @{$hosts}, $host_name; + } } - # If I am here, either there is no IPMI. Can we boot it using another fence method? - # Is the machine in an Anvil! system? - my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({host_uuid => $host_uuid}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); - if ($anvil_uuid) + my $host_count = @{$hosts}; + my $steps = int((80 / $host_count) / 3); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + host_count => $host_count, + steps => $steps, + }}); + + $anvil->data->{sys}{progress} = 5; + foreach my $host_name (sort {$a cmp $b} @{$hosts}) { - my $anvil_name = $anvil->Cluster->get_anvil_name({anvil_uuid => $anvil_uuid}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name }}); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "job_0331", variables => { - host_name => $host_name, - anvil_name => $anvil_name, + my $host_uuid = $anvil->Database->get_host_uuid_from_string({string => $host_name}); + my $host_ipmi = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}; + my $host_type = $anvil->data->{hosts}{host_uuid}{$host_uuid}{host_ipmi}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + host_uuid => $host_uuid, + host_name => $host_name, + host_ipmi => $anvil->Log->is_secure($host_ipmi), + host_type => $host_type, }}); - $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}+=10, message => "job_0331,!!host_name!".$host_name."!!,!!anvil_name!".$anvil_name."!!"}); - $anvil->Cluster->get_fence_methods({host_uuid => $host_uuid}); - foreach my $target_host_name (sort {$a cmp $b} keys %{$anvil->data->{fence_method}}) + $anvil->data->{sys}{progress} += $steps; + + if ($host_ipmi) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_name => $target_host_name }}); - foreach my $order (sort {$a cmp $b} keys %{$anvil->data->{fence_method}{$target_host_name}{order}}) + # Got it. + $anvil->data->{sys}{progress} += $steps; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "job_0327", variables => { host_name => $host_name }}); + $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "job_0327,!!host_name!".$host_name."!!"}); + + # First, is the node already on? + my $shell_call = $host_ipmi." -o status"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { shell_call => $shell_call }}); + + $anvil->data->{sys}{progress} += $steps; + my $problem = call_fence_agent($anvil, $shell_call, $anvil->data->{sys}{progress}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { problem => $problem }}); + + $anvil->data->{sys}{progress} += $steps; + if ($problem) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { order => $order }}); - foreach my $method (sort {$a cmp $b} keys %{$anvil->data->{fence_method}{$target_host_name}{order}{$order}{method}}) + # If I am here, there is no IPMI. Can we boot it using another fence method? + # The machine would have to be in an Anvil! for this to work. + my $anvil_uuid = $anvil->Cluster->get_anvil_uuid({host_uuid => $host_uuid}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_uuid => $anvil_uuid }}); + if ($anvil_uuid) { - next if $method =~ /pdu/; - my $shell_call = $anvil->data->{fence_method}{$target_host_name}{order}{$order}{method}{$method}{command}; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { - method => $method, - shell_call => $anvil->Log->is_secure($shell_call), + my $anvil_name = $anvil->Cluster->get_anvil_name({anvil_uuid => $anvil_uuid}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { anvil_name => $anvil_name }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, key => "job_0331", variables => { + host_name => $host_name, + anvil_name => $anvil_name, }}); - call_fence_agent($anvil, $shell_call); + $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "job_0331,!!host_name!".$host_name."!!,!!anvil_name!".$anvil_name."!!"}); + + $anvil->Cluster->get_fence_methods({host_uuid => $host_uuid}); + foreach my $target_host_name (sort {$a cmp $b} keys %{$anvil->data->{fence_method}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { target_host_name => $target_host_name }}); + foreach my $order (sort {$a cmp $b} keys %{$anvil->data->{fence_method}{$target_host_name}{order}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { order => $order }}); + foreach my $method (sort {$a cmp $b} keys %{$anvil->data->{fence_method}{$target_host_name}{order}{$order}{method}}) + { + next if $method =~ /pdu/; + my $shell_call = $anvil->data->{fence_method}{$target_host_name}{order}{$order}{method}{$method}{command}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + method => $method, + shell_call => $anvil->Log->is_secure($shell_call), + }}); + my $problem = call_fence_agent($anvil, $shell_call, $anvil->data->{sys}{progress}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { problem => $problem }}); + + if ($problem) + { + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0297"}); + $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "error_0297"}); + } + } + } + } + } + else + { + # Nothing we can do to boot this machine. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0294"}); + $anvil->Job->update_progress({progress => $anvil->data->{sys}{progress}, message => "error_0294"}); } + } } - - # If I hit here, we ran out of fence options and can't boot the machine. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0297"}); - $anvil->Job->update_progress({progress => 100, message => "error_0297"}); - $anvil->nice_exit({exit_code => 1}); - } - else - { - # Nothing we can do to boot this machine. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0294"}); - $anvil->Job->update_progress({progress => 100, message => "error_0294"}); - $anvil->nice_exit({exit_code => 1}); } + # Done. + $anvil->Job->update_progress({progress => 100, message => "message_0025"}); + $anvil->nice_exit({exit_code => 0}); + return(0); } # This calls a fence agent and exits if it successfully boots the target sub call_fence_agent { - my ($anvil, $shell_call) = @_; + my ($anvil, $shell_call, $progress) = @_; my ($output, $return_code) = $anvil->System->call({shell_call => $shell_call, secure => 1}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { @@ -212,14 +265,14 @@ sub call_fence_agent # The machine is already on $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "job_0328"}); $anvil->Job->update_progress({progress => 100, message => "job_0328"}); - $anvil->nice_exit({exit_code => 0}); + return(0); } elsif ($return_code eq "1") { # Unable to connect to the fence device. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0293", variables => { output => $output }}); $anvil->Job->update_progress({progress => 100, message => "error_0293,!!output!".$output."!!"}); - $anvil->nice_exit({exit_code => 1}); + return(1); } elsif ($return_code eq "2") { @@ -249,14 +302,14 @@ sub call_fence_agent host_uuid => $anvil->data->{switches}{'host-uuid'}, host_status => "booting", }); - $anvil->nice_exit({exit_code => 0}); + return(0); } else { # Failed. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0292", variables => { output => $output }}); $anvil->Job->update_progress({progress => 100, message => "error_0292,!!output!".$output."!!"}); - $anvil->nice_exit({exit_code => 1}); + return(1); } } From 24879a3ca8fd2731e721a247eef19fc82e378bf2 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 03:20:39 -0400 Subject: [PATCH 13/25] fix(striker-ui-api): don't throw when no servers found in anvil summary --- .../src/lib/request_handlers/anvil/buildAnvilSummary.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/anvil/buildAnvilSummary.ts b/striker-ui-api/src/lib/request_handlers/anvil/buildAnvilSummary.ts index 99be97a0..74672c74 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/buildAnvilSummary.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/buildAnvilSummary.ts @@ -60,8 +60,6 @@ export const buildAnvilSummary = async ({ throw error; } - if (!scounts.length) throw new Error(`No host server records found`); - for (const huuid of [n1uuid, n2uuid]) { const { host_uuid: { From b15df65c077dd958e61b9b4f2a6247136f4fa995 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 03:22:50 -0400 Subject: [PATCH 14/25] fix(striker-ui-api): catch exceptions in GET anvil summary list handler --- .../lib/request_handlers/anvil/getAnvilDetail.ts | 4 +--- .../lib/request_handlers/anvil/getAnvilSummary.ts | 14 ++++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts index abcf6461..bcdf6281 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilDetail.ts @@ -34,9 +34,7 @@ export const getAnvilDetail: RequestHandler< hosts, }); } catch (error) { - stderr( - `Failed to get summary of anvil node pair ${anvilUuid}; CAUSE: ${error}`, - ); + stderr(`Failed to get summary of anvil node ${anvilUuid}; CAUSE: ${error}`); return response.status(500).send(); } diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilSummary.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilSummary.ts index aae6e44b..2e0046d6 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilSummary.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilSummary.ts @@ -23,10 +23,16 @@ export const getAnvilSummary: RequestHandler = async ( const { anvil_uuid: alist } = anvils; const result: AnvilSummary = { anvils: [] }; - for (const auuid of Object.keys(alist)) { - result.anvils.push( - await buildAnvilSummary({ anvils, anvilUuid: auuid, hosts }), - ); + try { + for (const auuid of Object.keys(alist)) { + result.anvils.push( + await buildAnvilSummary({ anvils, anvilUuid: auuid, hosts }), + ); + } + } catch (error) { + stderr(`Failed to get summary of anvil nodes; CAUSE: ${error}`); + + return response.status(500).send(); } response.json(result); From 6babc33006a720cc1d955c004921f0327d436719 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 04:08:37 -0400 Subject: [PATCH 15/25] fix(striker-ui-api): ignore deleted servers in all servers-related queries --- .../lib/request_handlers/anvil/buildQueryAnvilDetail.ts | 7 ++++++- .../src/lib/request_handlers/anvil/getAnvilCpu.ts | 5 ++++- .../src/lib/request_handlers/anvil/getAnvilMemory.ts | 5 +++-- .../src/lib/request_handlers/server/createServer.ts | 8 ++++++-- .../src/lib/request_handlers/server/deleteServer.ts | 8 ++++++-- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/anvil/buildQueryAnvilDetail.ts b/striker-ui-api/src/lib/request_handlers/anvil/buildQueryAnvilDetail.ts index c07d2da9..8b504353 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/buildQueryAnvilDetail.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/buildQueryAnvilDetail.ts @@ -1,6 +1,10 @@ import { dSize } from 'format-data-size'; -import { NODE_AND_DR_RESERVED_MEMORY_SIZE, OS_LIST_MAP } from '../../consts'; +import { + DELETED, + NODE_AND_DR_RESERVED_MEMORY_SIZE, + OS_LIST_MAP, +} from '../../consts'; import join from '../../join'; import { stdoutVar } from '../../shell'; @@ -99,6 +103,7 @@ const buildQueryAnvilDetail = ({ FROM server_definitions AS ser_def ) AS pos_ser_def ON server_uuid = server_definition_server_uuid + WHERE ser.server_state != '${DELETED}' ${groupByPhrase}`; }; diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts index 9a0d9133..1c28d9e0 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts @@ -1,5 +1,7 @@ import { RequestHandler } from 'express'; +import { DELETED } from '../../consts'; + import { query } from '../../accessModule'; import { getShortHostName } from '../../disassembleHostName'; import { stderr } from '../../shell'; @@ -72,7 +74,8 @@ export const getAnvilCpu: RequestHandler = async ( FROM servers AS a JOIN server_definitions AS b ON a.server_uuid = b.server_definition_server_uuid - WHERE a.server_anvil_uuid = '${anvilUuid}';`, + WHERE a.server_state != '${DELETED}' + AND a.server_anvil_uuid = '${anvilUuid}';`, ); } catch (error) { stderr(`Failed to get anvil ${anvilUuid} server cpu info; CAUSE: ${error}`); diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilMemory.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilMemory.ts index 5adb3b4a..cb4105af 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilMemory.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilMemory.ts @@ -1,7 +1,7 @@ import { RequestHandler } from 'express'; import { DataSizeUnit, dSize } from 'format-data-size'; -import { NODE_AND_DR_RESERVED_MEMORY_SIZE } from '../../consts'; +import { DELETED, NODE_AND_DR_RESERVED_MEMORY_SIZE } from '../../consts'; import { query } from '../../accessModule'; import { stderr } from '../../shell'; @@ -88,7 +88,8 @@ export const getAnvilMemory: RequestHandler< FROM server_definitions AS a JOIN servers AS b ON b.server_uuid = a.server_definition_server_uuid - WHERE server_anvil_uuid = '${anvilUuid}';`, + WHERE b.server_state != '${DELETED}' + AND b.server_anvil_uuid = '${anvilUuid}';`, ); } catch (error) { stderr(`Failed to get anvil ${anvilUuid} server info; CAUSE: ${error}`); diff --git a/striker-ui-api/src/lib/request_handlers/server/createServer.ts b/striker-ui-api/src/lib/request_handlers/server/createServer.ts index b2746a1a..66e05446 100644 --- a/striker-ui-api/src/lib/request_handlers/server/createServer.ts +++ b/striker-ui-api/src/lib/request_handlers/server/createServer.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import { RequestHandler } from 'express'; -import { REP_UUID, SERVER_PATHS } from '../../consts'; +import { DELETED, REP_UUID, SERVER_PATHS } from '../../consts'; import { OS_LIST_MAP } from '../../consts/OS_LIST'; import { job, query } from '../../accessModule'; @@ -49,7 +49,11 @@ export const createServer: RequestHandler = async (request, response) => { ); const [[serverNameCount]] = await query( - `SELECT COUNT(server_uuid) FROM servers WHERE server_name = '${serverName}'`, + `SELECT + COUNT(server_uuid) + FROM servers + WHERE server_state != '${DELETED}' + AND server_name = '${serverName}'`, ); assert( diff --git a/striker-ui-api/src/lib/request_handlers/server/deleteServer.ts b/striker-ui-api/src/lib/request_handlers/server/deleteServer.ts index 99918213..2eb68496 100644 --- a/striker-ui-api/src/lib/request_handlers/server/deleteServer.ts +++ b/striker-ui-api/src/lib/request_handlers/server/deleteServer.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import { RequestHandler } from 'express'; -import { REP_UUID, SERVER_PATHS } from '../../consts'; +import { DELETED, REP_UUID, SERVER_PATHS } from '../../consts'; import { job, query } from '../../accessModule'; import { sanitize } from '../../sanitize'; @@ -39,7 +39,11 @@ export const deleteServer: RequestHandler< ); const rows: [[string]] = await query( - `SELECT server_host_uuid FROM servers WHERE server_uuid = '${serverUuid}';`, + `SELECT + server_host_uuid + FROM servers + WHERE server_state != '${DELETED}' + AND server_uuid = '${serverUuid}';`, ); assert.ok(rows.length, `Server ${serverUuid} not found`); From 6fce2258ba2b1e1b4686504428dd0073df87e73b Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 04:51:32 -0400 Subject: [PATCH 16/25] fix(striker-ui-api): find pre-def cpu vendor before extract first word --- striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts index 1c28d9e0..ba152df2 100644 --- a/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts +++ b/striker-ui-api/src/lib/request_handlers/anvil/getAnvilCpu.ts @@ -102,7 +102,8 @@ export const getAnvilCpu: RequestHandler = async ( const cores = Number(rCores); const threads = Number(rThreads); - const vendor = model.replace(/^(\w+).*$/, '$1'); + const matched = model.match(/amd|arm|intel|powerpc/i); + const vendor = matched ? matched[0] : model.replace(/^(\w+).*$/, '$1'); previous.hosts[uuid] = { cores, From 2dc0fd3835203bc3ef4bb5517766e1b6cf0a1173 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 05:01:58 -0400 Subject: [PATCH 17/25] fix(striker-ui-api): sort files by name --- .../src/lib/request_handlers/file/buildQueryFileDetail.ts | 3 ++- striker-ui-api/src/lib/request_handlers/file/getFile.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/file/buildQueryFileDetail.ts b/striker-ui-api/src/lib/request_handlers/file/buildQueryFileDetail.ts index e69bc04f..c63d8aa3 100644 --- a/striker-ui-api/src/lib/request_handlers/file/buildQueryFileDetail.ts +++ b/striker-ui-api/src/lib/request_handlers/file/buildQueryFileDetail.ts @@ -46,5 +46,6 @@ export const buildQueryFileDetail = ({ JOIN hosts AS hos ON fil_loc.file_location_host_uuid = hos.host_uuid WHERE fil.file_type != '${DELETED}' - ${condFileUUIDs};`; + ${condFileUUIDs} + ORDER BY fil.file_name ASC;`; }; diff --git a/striker-ui-api/src/lib/request_handlers/file/getFile.ts b/striker-ui-api/src/lib/request_handlers/file/getFile.ts index f8876ea9..831f61f1 100644 --- a/striker-ui-api/src/lib/request_handlers/file/getFile.ts +++ b/striker-ui-api/src/lib/request_handlers/file/getFile.ts @@ -17,7 +17,8 @@ export const getFile: RequestHandler = buildGetRequestHandler((request) => { file_type, file_md5sum FROM files - WHERE file_type != '${DELETED}';`; + WHERE file_type != '${DELETED}' + ORDER BY file_name ASC;`; if (fileUUIDs) { query = buildQueryFileDetail({ From df7b5fa3973b937ad226994360413e3b6bb5a746 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 05:11:20 -0400 Subject: [PATCH 18/25] fix(striker-ui-api): sort hosts by name --- .../src/lib/request_handlers/host/buildQueryHostDetail.ts | 3 ++- striker-ui-api/src/lib/request_handlers/host/getHost.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts b/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts index 4c1cde72..e0eb7855 100644 --- a/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts +++ b/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts @@ -75,7 +75,8 @@ export const buildQueryHostDetail: BuildQueryDetailFunction = ({ AND b.variable_value = c.network_interface_mac_address AND a.host_uuid = c.network_interface_host_uuid WHERE ${condHostUUIDs} - ORDER BY cvar_name ASC, + ORDER BY a.host_name ASC, + cvar_name ASC, b.variable_name ASC;`; const afterQueryReturn: QueryResultModifierFunction = diff --git a/striker-ui-api/src/lib/request_handlers/host/getHost.ts b/striker-ui-api/src/lib/request_handlers/host/getHost.ts index 1b47cdaa..e6071d62 100644 --- a/striker-ui-api/src/lib/request_handlers/host/getHost.ts +++ b/striker-ui-api/src/lib/request_handlers/host/getHost.ts @@ -29,7 +29,8 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => { hos.host_type, hos.host_uuid FROM hosts AS hos - ${condition};`; + ${condition} + ORDER BY hos.host_name ASC;`; let afterQueryReturn: QueryResultModifierFunction | undefined = buildQueryResultReducer<{ [hostUUID: string]: HostOverview }>( (previous, [hostName, hostType, hostUUID]) => { From 78b75c649a46898f438759d2c91944aba66730f2 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 05:50:36 -0400 Subject: [PATCH 19/25] fix(striker-ui-api): correct ID condition in query host detail --- striker-ui-api/src/lib/buildCondition.ts | 7 +++++-- .../src/lib/request_handlers/host/buildQueryHostDetail.ts | 4 ++-- striker-ui-api/src/lib/request_handlers/host/getHost.ts | 3 +++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/striker-ui-api/src/lib/buildCondition.ts b/striker-ui-api/src/lib/buildCondition.ts index b128322e..cdd7a99e 100644 --- a/striker-ui-api/src/lib/buildCondition.ts +++ b/striker-ui-api/src/lib/buildCondition.ts @@ -33,6 +33,9 @@ export const buildUnknownIDCondition = ( }; export const buildKnownIDCondition = ( - keys: string[] | '*' = '*', + keys: string[] | 'all' | '*' = 'all', conditionPrefix: string, -) => (keys[0] === '*' ? '' : buildIDCondition(keys, conditionPrefix)); +) => + !(keys instanceof Array) || keys.some((v) => ['all', '*'].includes(v)) + ? '' + : buildIDCondition(keys, conditionPrefix); diff --git a/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts b/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts index e0eb7855..5d6a33e2 100644 --- a/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts +++ b/striker-ui-api/src/lib/request_handlers/host/buildQueryHostDetail.ts @@ -42,7 +42,7 @@ const setCvar = ( export const buildQueryHostDetail: BuildQueryDetailFunction = ({ keys: hostUUIDs = '*', } = {}) => { - const condHostUUIDs = buildKnownIDCondition(hostUUIDs, 'a.host_uuid'); + const condHostUUIDs = buildKnownIDCondition(hostUUIDs, 'WHERE a.host_uuid'); stdout(`condHostUUIDs=[${condHostUUIDs}]`); @@ -74,7 +74,7 @@ export const buildQueryHostDetail: BuildQueryDetailFunction = ({ ON b.variable_name LIKE '%link%_mac%' AND b.variable_value = c.network_interface_mac_address AND a.host_uuid = c.network_interface_host_uuid - WHERE ${condHostUUIDs} + ${condHostUUIDs} ORDER BY a.host_name ASC, cvar_name ASC, b.variable_name ASC;`; diff --git a/striker-ui-api/src/lib/request_handlers/host/getHost.ts b/striker-ui-api/src/lib/request_handlers/host/getHost.ts index e6071d62..49d54391 100644 --- a/striker-ui-api/src/lib/request_handlers/host/getHost.ts +++ b/striker-ui-api/src/lib/request_handlers/host/getHost.ts @@ -49,6 +49,9 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => { ); if (hostUUIDs) { + // TODO: the output of host detail is designed to only contain one + // host, correct it to support multiple hosts to allow selecting + // multiple hosts' detail. ({ query, afterQueryReturn } = buildQueryHostDetail({ keys: sanitize(hostUUIDs, 'string[]', { modifierType: 'sql', From cf74fce91ed897fb29f1f85d2e579ad25ea9f9ae Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 16 Oct 2023 05:57:32 -0400 Subject: [PATCH 20/25] build(striker-ui-api): rebuild --- striker-ui-api/out/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui-api/out/index.js b/striker-ui-api/out/index.js index c235cd3a..7ce859f2 100644 --- a/striker-ui-api/out/index.js +++ b/striker-ui-api/out/index.js @@ -1,2 +1,2 @@ /*! For license information please see index.js.LICENSE.txt */ -(()=>{var e={9078:(e,t,n)=>{"use strict";var r=n(159),a=n(983);function o(e){if(!(this instanceof o))return new o(e);this.headers=e.headers,this.negotiator=new r(e)}function i(e){return-1===e.indexOf("/")?a.lookup(e):e}function s(e){return"string"==typeof e}e.exports=o,o.prototype.type=o.prototype.types=function(e){var t=e;if(t&&!Array.isArray(t)){t=new Array(arguments.length);for(var n=0;n{"use strict";function t(e,n,r){for(var a=0;a0&&Array.isArray(o)?t(o,n,r-1):n.push(o)}return n}function n(e,t){for(var r=0;r{"use strict";var r=n(412)("body-parser"),a=Object.create(null);function o(e){return function(){return function(e){var t=a[e];if(void 0!==t)return t;switch(e){case"json":t=n(6035);break;case"raw":t=n(187);break;case"text":t=n(6560);break;case"urlencoded":t=n(4861)}return a[e]=t}(e)}}t=e.exports=r.function((function(e){var n=Object.create(e||null,{type:{configurable:!0,enumerable:!0,value:void 0,writable:!0}}),r=t.urlencoded(n),a=t.json(n);return function(e,t,n){a(e,t,(function(a){if(a)return n(a);r(e,t,n)}))}}),"bodyParser: use individual json/urlencoded middlewares"),Object.defineProperty(t,"json",{configurable:!0,enumerable:!0,get:o("json")}),Object.defineProperty(t,"raw",{configurable:!0,enumerable:!0,get:o("raw")}),Object.defineProperty(t,"text",{configurable:!0,enumerable:!0,get:o("text")}),Object.defineProperty(t,"urlencoded",{configurable:!0,enumerable:!0,get:o("urlencoded")})},3211:(e,t,n)=>{"use strict";var r=n(9009),a=n(6149),o=n(1045),i=n(4914),s=n(338),c=n(8170),u=n(9796);e.exports=function(e,t,n,p,l,d){var f,m,v=d;e._body=!0;var h=null!==v.encoding?v.encoding:null,b=v.verify;try{m=function(e,t,n){var a,o=(e.headers["content-encoding"]||"identity").toLowerCase(),i=e.headers["content-length"];if(t('content-encoding "%s"',o),!1===n&&"identity"!==o)throw r(415,"content encoding unsupported",{encoding:o,type:"encoding.unsupported"});switch(o){case"deflate":a=u.createInflate(),t("inflate body"),e.pipe(a);break;case"gzip":a=u.createGunzip(),t("gunzip body"),e.pipe(a);break;case"identity":(a=e).length=i;break;default:throw r(415,'unsupported content encoding "'+o+'"',{encoding:o,type:"encoding.unsupported"})}return a}(e,l,v.inflate),f=m.length,m.length=void 0}catch(e){return n(e)}if(v.length=f,v.encoding=b?null:h,null===v.encoding&&null!==h&&!i.encodingExists(h))return n(r(415,'unsupported charset "'+h.toUpperCase()+'"',{charset:h.toLowerCase(),type:"charset.unsupported"}));l("read body"),o(m,v,(function(o,u){var d;if(o)return d="encoding.unsupported"===o.type?r(415,'unsupported charset "'+h.toUpperCase()+'"',{charset:h.toLowerCase(),type:"charset.unsupported"}):r(400,o),m!==e&&(c(e),a(m,!0)),void function(e,t){s.isFinished(e)?t():(s(e,t),e.resume())}(e,(function(){n(r(400,d))}));if(b)try{l("verify body"),b(e,t,u,h)}catch(e){return void n(r(403,e,{body:u,type:e.type||"entity.verify.failed"}))}var f=u;try{l("parse body"),f="string"!=typeof u&&null!==h?i.decode(u,h):u,e.body=p(f)}catch(e){return void n(r(400,e,{body:f,type:e.type||"entity.parse.failed"}))}n()}))}},6035:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(9009),i=n(5158)("body-parser:json"),s=n(3211),c=n(273);e.exports=function(e){var t=e||{},n="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,l=!1!==t.inflate,d=t.reviver,f=!1!==t.strict,m=t.type||"application/json",v=t.verify||!1;if(!1!==v&&"function"!=typeof v)throw new TypeError("option verify must be function");var h="function"!=typeof m?function(e){return function(t){return Boolean(c(t,e))}}(m):m;function b(e){if(0===e.length)return{};if(f){var t=(n=e,(r=u.exec(n))?r[1]:void 0);if("{"!==t&&"["!==t)throw i("strict violation"),function(e,t){var n=e.indexOf(t),r=-1!==n?e.substring(0,n)+"#":"";try{throw JSON.parse(r),new SyntaxError("strict violation")}catch(e){return p(e,{message:e.message.replace("#",t),stack:e.stack})}}(e,t)}var n,r;try{return i("parse json"),JSON.parse(e,d)}catch(e){throw p(e,{message:e.message,stack:e.stack})}}return function(e,t,r){if(e._body)return i("body already parsed"),void r();if(e.body=e.body||{},!c.hasBody(e))return i("skip empty body"),void r();if(i("content-type %j",e.headers["content-type"]),!h(e))return i("skip parsing"),void r();var u=function(e){try{return(a.parse(e).parameters.charset||"").toLowerCase()}catch(e){return}}(e)||"utf-8";if("utf-"!==u.slice(0,4))return i("invalid charset"),void r(o(415,'unsupported charset "'+u.toUpperCase()+'"',{charset:u,type:"charset.unsupported"}));s(e,t,r,b,i,{encoding:u,inflate:l,limit:n,verify:v})}};var u=/^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/;function p(e,t){for(var n=Object.getOwnPropertyNames(e),r=0;r{"use strict";var r=n(9830),a=n(5158)("body-parser:raw"),o=n(3211),i=n(273);e.exports=function(e){var t=e||{},n=!1!==t.inflate,s="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,c=t.type||"application/octet-stream",u=t.verify||!1;if(!1!==u&&"function"!=typeof u)throw new TypeError("option verify must be function");var p="function"!=typeof c?function(e){return function(t){return Boolean(i(t,e))}}(c):c;function l(e){return e}return function(e,t,r){return e._body?(a("body already parsed"),void r()):(e.body=e.body||{},i.hasBody(e)?(a("content-type %j",e.headers["content-type"]),p(e)?void o(e,t,r,l,a,{encoding:null,inflate:n,limit:s,verify:u}):(a("skip parsing"),void r())):(a("skip empty body"),void r()))}}},6560:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(5158)("body-parser:text"),i=n(3211),s=n(273);e.exports=function(e){var t=e||{},n=t.defaultCharset||"utf-8",c=!1!==t.inflate,u="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,p=t.type||"text/plain",l=t.verify||!1;if(!1!==l&&"function"!=typeof l)throw new TypeError("option verify must be function");var d="function"!=typeof p?function(e){return function(t){return Boolean(s(t,e))}}(p):p;function f(e){return e}return function(e,t,r){if(e._body)return o("body already parsed"),void r();if(e.body=e.body||{},!s.hasBody(e))return o("skip empty body"),void r();if(o("content-type %j",e.headers["content-type"]),!d(e))return o("skip parsing"),void r();var p=function(e){try{return(a.parse(e).parameters.charset||"").toLowerCase()}catch(e){return}}(e)||n;i(e,t,r,f,o,{encoding:p,inflate:c,limit:u,verify:l})}}},4861:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(9009),i=n(5158)("body-parser:urlencoded"),s=n(412)("body-parser"),c=n(3211),u=n(273);e.exports=function(e){var t=e||{};void 0===t.extended&&s("undefined extended: provide extended option");var n=!1!==t.extended,p=!1!==t.inflate,f="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,m=t.type||"application/x-www-form-urlencoded",v=t.verify||!1;if(!1!==v&&"function"!=typeof v)throw new TypeError("option verify must be function");var h=n?function(e){var t=void 0!==e.parameterLimit?e.parameterLimit:1e3,n=d("qs");if(isNaN(t)||t<1)throw new TypeError("option parameterLimit must be a positive number");return isFinite(t)&&(t|=0),function(e){var r=l(e,t);if(void 0===r)throw i("too many parameters"),o(413,"too many parameters",{type:"parameters.too.many"});var a=Math.max(100,r);return i("parse extended urlencoding"),n(e,{allowPrototypes:!0,arrayLimit:a,depth:1/0,parameterLimit:t})}}(t):function(e){var t=void 0!==e.parameterLimit?e.parameterLimit:1e3,n=d("querystring");if(isNaN(t)||t<1)throw new TypeError("option parameterLimit must be a positive number");return isFinite(t)&&(t|=0),function(e){if(void 0===l(e,t))throw i("too many parameters"),o(413,"too many parameters",{type:"parameters.too.many"});return i("parse urlencoding"),n(e,void 0,void 0,{maxKeys:t})}}(t),b="function"!=typeof m?function(e){return function(t){return Boolean(u(t,e))}}(m):m;function g(e){return e.length?h(e):{}}return function(e,t,n){if(e._body)return i("body already parsed"),void n();if(e.body=e.body||{},!u.hasBody(e))return i("skip empty body"),void n();if(i("content-type %j",e.headers["content-type"]),!b(e))return i("skip parsing"),void n();var r=function(e){try{return(a.parse(e).parameters.charset||"").toLowerCase()}catch(e){return}}(e)||"utf-8";if("utf-8"!==r)return i("invalid charset"),void n(o(415,'unsupported charset "'+r.toUpperCase()+'"',{charset:r,type:"charset.unsupported"}));c(e,t,n,g,i,{debug:i,encoding:r,inflate:p,limit:f,verify:v})}};var p=Object.create(null);function l(e,t){for(var n=0,r=0;-1!==(r=e.indexOf("&",r));)if(r++,++n===t)return;return n}function d(e){var t=p[e];if(void 0!==t)return t.parse;switch(e){case"qs":t=n(129);break;case"querystring":t=n(3477)}return p[e]=t,t.parse}},6744:(e,t,n)=>{"use strict";const r=n(3349),a=n(7529),o=n(8050),i=n(4339),s=(e,t={})=>{let n=[];if(Array.isArray(e))for(let r of e){let e=s.create(r,t);Array.isArray(e)?n.push(...e):n.push(e)}else n=[].concat(s.create(e,t));return t&&!0===t.expand&&!0===t.nodupes&&(n=[...new Set(n)]),n};s.parse=(e,t={})=>i(e,t),s.stringify=(e,t={})=>r("string"==typeof e?s.parse(e,t):e,t),s.compile=(e,t={})=>("string"==typeof e&&(e=s.parse(e,t)),a(e,t)),s.expand=(e,t={})=>{"string"==typeof e&&(e=s.parse(e,t));let n=o(e,t);return!0===t.noempty&&(n=n.filter(Boolean)),!0===t.nodupes&&(n=[...new Set(n)]),n},s.create=(e,t={})=>""===e||e.length<3?[e]:!0!==t.expand?s.compile(e,t):s.expand(e,t),e.exports=s},7529:(e,t,n)=>{"use strict";const r=n(2664),a=n(3083);e.exports=(e,t={})=>{let n=(e,o={})=>{let i=a.isInvalidBrace(o),s=!0===e.invalid&&!0===t.escapeInvalid,c=!0===i||!0===s,u=!0===t.escapeInvalid?"\\":"",p="";if(!0===e.isOpen)return u+e.value;if(!0===e.isClose)return u+e.value;if("open"===e.type)return c?u+e.value:"(";if("close"===e.type)return c?u+e.value:")";if("comma"===e.type)return"comma"===e.prev.type?"":c?e.value:"|";if(e.value)return e.value;if(e.nodes&&e.ranges>0){let n=a.reduce(e.nodes),o=r(...n,{...t,wrap:!1,toRegex:!0});if(0!==o.length)return n.length>1&&o.length>1?`(${o})`:o}if(e.nodes)for(let t of e.nodes)p+=n(t,e);return p};return n(e)}},6611:e=>{"use strict";e.exports={MAX_LENGTH:65536,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:"\n",CHAR_NO_BREAK_SPACE:" ",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:"\t",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\ufeff"}},8050:(e,t,n)=>{"use strict";const r=n(2664),a=n(3349),o=n(3083),i=(e="",t="",n=!1)=>{let r=[];if(e=[].concat(e),!(t=[].concat(t)).length)return e;if(!e.length)return n?o.flatten(t).map((e=>`{${e}}`)):t;for(let a of e)if(Array.isArray(a))for(let e of a)r.push(i(e,t,n));else for(let e of t)!0===n&&"string"==typeof e&&(e=`{${e}}`),r.push(Array.isArray(e)?i(a,e,n):a+e);return o.flatten(r)};e.exports=(e,t={})=>{let n=void 0===t.rangeLimit?1e3:t.rangeLimit,s=(e,c={})=>{e.queue=[];let u=c,p=c.queue;for(;"brace"!==u.type&&"root"!==u.type&&u.parent;)u=u.parent,p=u.queue;if(e.invalid||e.dollar)return void p.push(i(p.pop(),a(e,t)));if("brace"===e.type&&!0!==e.invalid&&2===e.nodes.length)return void p.push(i(p.pop(),["{}"]));if(e.nodes&&e.ranges>0){let s=o.reduce(e.nodes);if(o.exceedsLimit(...s,t.step,n))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let c=r(...s,t);return 0===c.length&&(c=a(e,t)),p.push(i(p.pop(),c)),void(e.nodes=[])}let l=o.encloseBrace(e),d=e.queue,f=e;for(;"brace"!==f.type&&"root"!==f.type&&f.parent;)f=f.parent,d=f.queue;for(let t=0;t{"use strict";const r=n(3349),{MAX_LENGTH:a,CHAR_BACKSLASH:o,CHAR_BACKTICK:i,CHAR_COMMA:s,CHAR_DOT:c,CHAR_LEFT_PARENTHESES:u,CHAR_RIGHT_PARENTHESES:p,CHAR_LEFT_CURLY_BRACE:l,CHAR_RIGHT_CURLY_BRACE:d,CHAR_LEFT_SQUARE_BRACKET:f,CHAR_RIGHT_SQUARE_BRACKET:m,CHAR_DOUBLE_QUOTE:v,CHAR_SINGLE_QUOTE:h,CHAR_NO_BREAK_SPACE:b,CHAR_ZERO_WIDTH_NOBREAK_SPACE:g}=n(6611);e.exports=(e,t={})=>{if("string"!=typeof e)throw new TypeError("Expected a string");let n=t||{},y="number"==typeof n.maxLength?Math.min(a,n.maxLength):a;if(e.length>y)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${y})`);let x,w={type:"root",input:e,nodes:[]},_=[w],S=w,k=w,E=0,A=e.length,j=0,O=0;const C=()=>e[j++],R=e=>{if("text"===e.type&&"dot"===k.type&&(k.type="text"),!k||"text"!==k.type||"text"!==e.type)return S.nodes.push(e),e.parent=S,e.prev=k,k=e,e;k.value+=e.value};for(R({type:"bos"});j0){if(S.ranges>0){S.ranges=0;let e=S.nodes.shift();S.nodes=[e,{type:"text",value:r(S)}]}R({type:"comma",value:x}),S.commas++}else if(x===c&&O>0&&0===S.commas){let e=S.nodes;if(0===O||0===e.length){R({type:"text",value:x});continue}if("dot"===k.type){if(S.range=[],k.value+=x,k.type="range",3!==S.nodes.length&&5!==S.nodes.length){S.invalid=!0,S.ranges=0,k.type="text";continue}S.ranges++,S.args=[];continue}if("range"===k.type){e.pop();let t=e[e.length-1];t.value+=k.value+x,k=t,S.ranges--;continue}R({type:"dot",value:x})}else R({type:"text",value:x});else{if("brace"!==S.type){R({type:"text",value:x});continue}let e="close";S=_.pop(),S.close=!0,R({type:e,value:x}),O--,S=_[_.length-1]}else{O++;let e=k.value&&"$"===k.value.slice(-1)||!0===S.dollar;S=R({type:"brace",open:!0,close:!1,dollar:e,depth:O,commas:0,ranges:0,nodes:[]}),_.push(S),R({type:"open",value:x})}else{let e,n=x;for(!0!==t.keepQuotes&&(x="");j{e.nodes||("open"===e.type&&(e.isOpen=!0),"close"===e.type&&(e.isClose=!0),e.nodes||(e.type="text"),e.invalid=!0)}));let e=_[_.length-1],t=e.nodes.indexOf(S);e.nodes.splice(t,1,...S.nodes)}}while(_.length>0);return R({type:"eos"}),w}},3349:(e,t,n)=>{"use strict";const r=n(3083);e.exports=(e,t={})=>{let n=(e,a={})=>{let o=t.escapeInvalid&&r.isInvalidBrace(a),i=!0===e.invalid&&!0===t.escapeInvalid,s="";if(e.value)return(o||i)&&r.isOpenOrClose(e)?"\\"+e.value:e.value;if(e.value)return e.value;if(e.nodes)for(let t of e.nodes)s+=n(t);return s};return n(e)}},3083:(e,t)=>{"use strict";t.isInteger=e=>"number"==typeof e?Number.isInteger(e):"string"==typeof e&&""!==e.trim()&&Number.isInteger(Number(e)),t.find=(e,t)=>e.nodes.find((e=>e.type===t)),t.exceedsLimit=(e,n,r=1,a)=>!1!==a&&!(!t.isInteger(e)||!t.isInteger(n))&&(Number(n)-Number(e))/Number(r)>=a,t.escapeNode=(e,t=0,n)=>{let r=e.nodes[t];r&&(n&&r.type===n||"open"===r.type||"close"===r.type)&&!0!==r.escaped&&(r.value="\\"+r.value,r.escaped=!0)},t.encloseBrace=e=>"brace"===e.type&&e.commas>>0+e.ranges>>0==0&&(e.invalid=!0,!0),t.isInvalidBrace=e=>!("brace"!==e.type||!0!==e.invalid&&!e.dollar&&(e.commas>>0+e.ranges>>0!=0&&!0===e.open&&!0===e.close||(e.invalid=!0,0))),t.isOpenOrClose=e=>"open"===e.type||"close"===e.type||!0===e.open||!0===e.close,t.reduce=e=>e.reduce(((e,t)=>("text"===t.type&&e.push(t.value),"range"===t.type&&(t.type="text"),e)),[]),t.flatten=(...e)=>{const t=[],n=e=>{for(let r=0;r{"use strict";const{parseContentType:r}=n(1510),a=[n(7626),n(4403)].filter((function(e){return"function"==typeof e.detect}));e.exports=e=>{if("object"==typeof e&&null!==e||(e={}),"object"!=typeof e.headers||null===e.headers||"string"!=typeof e.headers["content-type"])throw new Error("Missing Content-Type");return function(e){const t=e.headers,n=r(t["content-type"]);if(!n)throw new Error("Malformed content type");for(const r of a){if(!r.detect(n))continue;const a={limits:e.limits,headers:t,conType:n,highWaterMark:void 0,fileHwm:void 0,defCharset:void 0,defParamCharset:void 0,preservePath:!1};return e.highWaterMark&&(a.highWaterMark=e.highWaterMark),e.fileHwm&&(a.fileHwm=e.fileHwm),a.defCharset=e.defCharset,a.defParamCharset=e.defParamCharset,a.preservePath=e.preservePath,new r(a)}throw new Error(`Unsupported content type: ${t["content-type"]}`)}(e)}},7626:(e,t,n)=>{"use strict";const{Readable:r,Writable:a}=n(2781),o=n(1301),{basename:i,convertToUTF8:s,getDecoder:c,parseContentType:u,parseDisposition:p}=n(1510),l=Buffer.from("\r\n"),d=Buffer.from("\r"),f=Buffer.from("-");function m(){}const v=16384;class h{constructor(e){this.header=Object.create(null),this.pairCount=0,this.byteCount=0,this.state=0,this.name="",this.value="",this.crlf=0,this.cb=e}reset(){this.header=Object.create(null),this.pairCount=0,this.byteCount=0,this.state=0,this.name="",this.value="",this.crlf=0}push(e,t,n){let r=t;for(;t{if(this._read(),0==--t._fileEndsLeft&&t._finalcb){const e=t._finalcb;t._finalcb=null,process.nextTick(e)}}))}_read(e){const t=this._readcb;t&&(this._readcb=null,t())}}const g={push:(e,t)=>{},destroy:()=>{}};function y(e,t){return e}function x(e,t,n){if(n)return t(n);t(n=w(e))}function w(e){if(e._hparser)return new Error("Malformed part header");const t=e._fileStream;return t&&(e._fileStream=null,t.destroy(new Error("Unexpected end of file"))),e._complete?void 0:new Error("Unexpected end of form")}const _=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],S=[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];e.exports=class extends a{constructor(e){if(super({autoDestroy:!0,emitClose:!0,highWaterMark:"number"==typeof e.highWaterMark?e.highWaterMark:void 0}),!e.conType.params||"string"!=typeof e.conType.params.boundary)throw new Error("Multipart: Boundary not found");const t=e.conType.params.boundary,n="string"==typeof e.defParamCharset&&e.defParamCharset?c(e.defParamCharset):y,r=e.defCharset||"utf8",a=e.preservePath,v={autoDestroy:!0,emitClose:!0,highWaterMark:"number"==typeof e.fileHwm?e.fileHwm:void 0},x=e.limits,w=x&&"number"==typeof x.fieldSize?x.fieldSize:1048576,_=x&&"number"==typeof x.fileSize?x.fileSize:1/0,S=x&&"number"==typeof x.files?x.files:1/0,k=x&&"number"==typeof x.fields?x.fields:1/0,E=x&&"number"==typeof x.parts?x.parts:1/0;let A=-1,j=0,O=0,C=!1;this._fileEndsLeft=0,this._fileStream=void 0,this._complete=!1;let R,T,I,P,U,N=0,D=0,L=!1,M=!1,F=!1;this._hparser=null;const q=new h((e=>{let t;if(this._hparser=null,C=!1,P="text/plain",T=r,I="7bit",U=void 0,L=!1,!e["content-disposition"])return void(C=!0);const o=p(e["content-disposition"][0],n);if(o&&"form-data"===o.type){if(o.params&&(o.params.name&&(U=o.params.name),o.params["filename*"]?t=o.params["filename*"]:o.params.filename&&(t=o.params.filename),void 0===t||a||(t=i(t))),e["content-type"]){const t=u(e["content-type"][0]);t&&(P=`${t.type}/${t.subtype}`,t.params&&"string"==typeof t.params.charset&&(T=t.params.charset.toLowerCase()))}if(e["content-transfer-encoding"]&&(I=e["content-transfer-encoding"][0].toLowerCase()),"application/octet-stream"===P||void 0!==t){if(O===S)return M||(M=!0,this.emit("filesLimit")),void(C=!0);if(++O,0===this.listenerCount("file"))return void(C=!0);N=0,this._fileStream=new b(v,this),++this._fileEndsLeft,this.emit("file",U,this._fileStream,{filename:t,encoding:I,mimeType:P})}else{if(j===k)return F||(F=!0,this.emit("fieldsLimit")),void(C=!0);if(++j,0===this.listenerCount("field"))return void(C=!0);R=[],D=0}}else C=!0}));let B=0;const H=(e,t,n,r,a)=>{e:for(;t;){if(null!==this._hparser){const e=this._hparser.push(t,n,r);if(-1===e){this._hparser=null,q.reset(),this.emit("error",new Error("Malformed part header"));break}n=e}if(n===r)break;if(0!==B){if(1===B){switch(t[n]){case 45:B=2,++n;break;case 13:B=3,++n;break;default:B=0}if(n===r)return}if(2===B){if(B=0,45===t[n])return this._complete=!0,void(this._bparser=g);const e=this._writecb;this._writecb=m,H(!1,f,0,1,!1),this._writecb=e}else if(3===B){if(B=0,10===t[n]){if(++n,A>=E)break;if(this._hparser=q,n===r)break;continue e}{const e=this._writecb;this._writecb=m,H(!1,d,0,1,!1),this._writecb=e}}}if(!C)if(this._fileStream){let e;const o=Math.min(r-n,_-N);a?e=t.slice(n,n+o):(e=Buffer.allocUnsafe(o),t.copy(e,0,n,n+o)),N+=e.length,N===_?(e.length>0&&this._fileStream.push(e),this._fileStream.emit("limit"),this._fileStream.truncated=!0,C=!0):this._fileStream.push(e)||(this._writecb&&(this._fileStream._readcb=this._writecb),this._writecb=null)}else if(void 0!==R){let e;const o=Math.min(r-n,w-D);a?e=t.slice(n,n+o):(e=Buffer.allocUnsafe(o),t.copy(e,0,n,n+o)),D+=o,R.push(e),D===w&&(C=!0,L=!0)}break}if(e){if(B=1,this._fileStream)this._fileStream.push(null),this._fileStream=null;else if(void 0!==R){let e;switch(R.length){case 0:e="";break;case 1:e=s(R[0],T,0);break;default:e=s(Buffer.concat(R,D),T,0)}R=void 0,D=0,this.emit("field",U,e,{nameTruncated:!1,valueTruncated:L,encoding:I,mimeType:P})}++A===E&&this.emit("partsLimit")}};this._bparser=new o(`\r\n--${t}`,H),this._writecb=null,this._finalcb=null,this.write(l)}static detect(e){return"multipart"===e.type&&"form-data"===e.subtype}_write(e,t,n){this._writecb=n,this._bparser.push(e,0),this._writecb&&function(e,t){const n=e._writecb;e._writecb=null,n&&n()}(this)}_destroy(e,t){this._hparser=null,this._bparser=g,e||(e=w(this));const n=this._fileStream;n&&(this._fileStream=null,n.destroy(e)),t(e)}_final(e){if(this._bparser.destroy(),!this._complete)return e(new Error("Unexpected end of form"));this._fileEndsLeft?this._finalcb=x.bind(null,this,e):x(this,e)}}},4403:(e,t,n)=>{"use strict";const{Writable:r}=n(2781),{getDecoder:a}=n(1510);function o(e,t,n,r){if(n>=r)return r;if(-1===e._byte){const a=c[t[n++]];if(-1===a)return-1;if(a>=8&&(e._encode=2),ne.fieldNameSizeLimit){for(e._keyTrunc||e._lastPose.fieldSizeLimit){for(e._valTrunc||e._lastPos=this.fieldsLimit)return n();let r=0;const a=e.length;if(this._lastPos=0,-2!==this._byte){if(r=o(this,e,r,a),-1===r)return n(new Error("Malformed urlencoded form"));if(r>=a)return n();this._inKey?++this._bytesKey:++this._bytesVal}e:for(;r0&&this.emit("field",this._key,"",{nameTruncated:this._keyTrunc,valueTruncated:!1,encoding:this.charset,mimeType:"text/plain"}),this._key="",this._val="",this._keyTrunc=!1,this._valTrunc=!1,this._bytesKey=0,this._bytesVal=0,++this._fields>=this.fieldsLimit)return this.emit("fieldsLimit"),n();continue;case 43:this._lastPos=a)return n();++this._bytesKey,r=i(this,e,r,a);continue}++r,++this._bytesKey,r=i(this,e,r,a)}this._lastPos0||this._bytesVal>0)&&this.emit("field",this._key,this._val,{nameTruncated:this._keyTrunc,valueTruncated:this._valTrunc,encoding:this.charset,mimeType:"text/plain"}),this._key="",this._val="",this._keyTrunc=!1,this._valTrunc=!1,this._bytesKey=0,this._bytesVal=0,++this._fields>=this.fieldsLimit)return this.emit("fieldsLimit"),n();continue e;case 43:this._lastPos=a)return n();++this._bytesVal,r=s(this,e,r,a);continue}++r,++this._bytesVal,r=s(this,e,r,a)}this._lastPos0||this._bytesVal>0)&&(this._inKey?this._key=this._decoder(this._key,this._encode):this._val=this._decoder(this._val,this._encode),this.emit("field",this._key,this._val,{nameTruncated:this._keyTrunc,valueTruncated:this._valTrunc,encoding:this.charset,mimeType:"text/plain"})),e()}}},1510:function(e){"use strict";function t(e,t,n){for(;t=128?r=2:0===r&&(r=1);continue}return}break}}if(m+=e.slice(d,t),m=o(m,f,r),void 0===m)return}else{if(++t===e.length)return;if(34===e.charCodeAt(t)){d=++t;let n=!1;for(;t{if(0===e.length)return"";if("string"==typeof e){if(t<2)return e;e=Buffer.from(e,"latin1")}return e.utf8Slice(0,e.length)},latin1:(e,t)=>0===e.length?"":"string"==typeof e?e:e.latin1Slice(0,e.length),utf16le:(e,t)=>0===e.length?"":("string"==typeof e&&(e=Buffer.from(e,"latin1")),e.ucs2Slice(0,e.length)),base64:(e,t)=>0===e.length?"":("string"==typeof e&&(e=Buffer.from(e,"latin1")),e.base64Slice(0,e.length)),other:(e,t)=>{if(0===e.length)return"";"string"==typeof e&&(e=Buffer.from(e,"latin1"));try{return new TextDecoder(this).decode(e)}catch{}}};function o(e,t,n){const a=r(t);if(a)return a(e,n)}const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],s=[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],c=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],u=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],p=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];e.exports={basename:function(e){if("string"!=typeof e)return"";for(let t=e.length-1;t>=0;--t)switch(e.charCodeAt(t)){case 47:case 92:return".."===(e=e.slice(t+1))||"."===e?"":e}return".."===e||"."===e?"":e},convertToUTF8:o,getDecoder:r,parseContentType:function(e){if(0===e.length)return;const n=Object.create(null);let r=0;for(;r{"use strict";e.exports=function(e,t){return"string"==typeof e?i(e):"number"==typeof e?o(e,t):null},e.exports.format=o,e.exports.parse=i;var t=/\B(?=(\d{3})+(?!\d))/g,n=/(?:\.0*|(\.[^0]+)0+)$/,r={b:1,kb:1024,mb:1<<20,gb:1<<30,tb:Math.pow(1024,4),pb:Math.pow(1024,5)},a=/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;function o(e,a){if(!Number.isFinite(e))return null;var o=Math.abs(e),i=a&&a.thousandsSeparator||"",s=a&&a.unitSeparator||"",c=a&&void 0!==a.decimalPlaces?a.decimalPlaces:2,u=Boolean(a&&a.fixedDecimals),p=a&&a.unit||"";p&&r[p.toLowerCase()]||(p=o>=r.pb?"PB":o>=r.tb?"TB":o>=r.gb?"GB":o>=r.mb?"MB":o>=r.kb?"KB":"B");var l=(e/r[p.toLowerCase()]).toFixed(c);return u||(l=l.replace(n,"$1")),i&&(l=l.split(".").map((function(e,n){return 0===n?e.replace(t,i):e})).join(".")),l+s+p}function i(e){if("number"==typeof e&&!isNaN(e))return e;if("string"!=typeof e)return null;var t,n=a.exec(e),o="b";return n?(t=parseFloat(n[1]),o=n[4].toLowerCase()):(t=parseInt(e,10),o="b"),isNaN(t)?null:Math.floor(r[o]*t)}},1924:(e,t,n)=>{"use strict";var r=n(210),a=n(5559),o=a(r("String.prototype.indexOf"));e.exports=function(e,t){var n=r(e,!!t);return"function"==typeof n&&o(e,".prototype.")>-1?a(n):n}},5559:(e,t,n)=>{"use strict";var r=n(8612),a=n(210),o=a("%Function.prototype.apply%"),i=a("%Function.prototype.call%"),s=a("%Reflect.apply%",!0)||r.call(i,o),c=a("%Object.getOwnPropertyDescriptor%",!0),u=a("%Object.defineProperty%",!0),p=a("%Math.max%");if(u)try{u({},"a",{value:1})}catch(e){u=null}e.exports=function(e){var t=s(r,i,arguments);if(c&&u){var n=c(t,"length");n.configurable&&u(t,"length",{value:1+p(0,e.length-(arguments.length-1))})}return t};var l=function(){return s(r,o,arguments)};u?u(e.exports,"apply",{value:l}):e.exports.apply=l},7389:(e,t,n)=>{"use strict";e.exports=function(e,t){var n=t||{},a=n.type||"attachment",o=function(e,t){if(void 0!==e){var n={};if("string"!=typeof e)throw new TypeError("filename must be a string");if(void 0===t&&(t=!0),"string"!=typeof t&&"boolean"!=typeof t)throw new TypeError("fallback must be a string or boolean");if("string"==typeof t&&c.test(t))throw new TypeError("fallback must be ISO-8859-1 string");var a=r(e),o=d.test(a),s="string"!=typeof t?t&&b(a):r(t),u="string"==typeof s&&s!==a;return(u||!o||i.test(a))&&(n["filename*"]=a),(o||u)&&(n.filename=u?s:a),n}}(e,n.fallback);return function(e){var t=e.parameters,n=e.type;if(!n||"string"!=typeof n||!f.test(n))throw new TypeError("invalid type");var r=String(n).toLowerCase();if(t&&"object"==typeof t)for(var a,o=Object.keys(t).sort(),i=0;i?@[\\\]{}\x7f]/g,i=/%[0-9A-Fa-f]{2}/,s=/%([0-9A-Fa-f]{2})/g,c=/[^\x20-\x7e\xa0-\xff]/g,u=/\\([\u0000-\u007f])/g,p=/([\\"])/g,l=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g,d=/^[\x20-\x7e\x80-\xff]+$/,f=/^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/,m=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/,v=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function h(e){var t=m.exec(e);if(!t)throw new TypeError("invalid extended field value");var n,r=t[1].toLowerCase(),o=t[2].replace(s,g);switch(r){case"iso-8859-1":n=b(o);break;case"utf-8":n=a.from(o,"binary").toString("utf8");break;default:throw new TypeError("unsupported charset in extended field")}return n}function b(e){return String(e).replace(c,"?")}function g(e,t){return String.fromCharCode(parseInt(t,16))}function y(e){return"%"+String(e).charCodeAt(0).toString(16).toUpperCase()}function x(e){return'"'+String(e).replace(p,"\\$1")+'"'}function w(e){var t=String(e);return"UTF-8''"+encodeURIComponent(t).replace(o,y)}function _(e,t){this.type=e,this.parameters=t}},7296:(e,t,n)=>{var r=n(4300),a=r.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function i(e,t,n){return a(e,t,n)}a.from&&a.alloc&&a.allocUnsafe&&a.allocUnsafeSlow?e.exports=r:(o(r,t),t.Buffer=i),i.prototype=Object.create(a.prototype),o(a,i),i.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return a(e,t,n)},i.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=a(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},i.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return a(e)},i.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},7811:(e,t)=>{"use strict";var n=/; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g,r=/^[\u000b\u0020-\u007e\u0080-\u00ff]+$/,a=/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/,o=/\\([\u000b\u0020-\u00ff])/g,i=/([\\"])/g,s=/^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;function c(e){var t=String(e);if(a.test(t))return t;if(t.length>0&&!r.test(t))throw new TypeError("invalid parameter value");return'"'+t.replace(i,"\\$1")+'"'}function u(e){this.parameters=Object.create(null),this.type=e}t.format=function(e){if(!e||"object"!=typeof e)throw new TypeError("argument obj is required");var t=e.parameters,n=e.type;if(!n||!s.test(n))throw new TypeError("invalid type");var r=n;if(t&&"object"==typeof t)for(var o,i=Object.keys(t).sort(),u=0;u{var r=n(6113);function a(e){return r.createHash("sha1").update(e).digest("hex")}t.sign=function(e,t){if("string"!=typeof e)throw new TypeError("Cookie value must be provided as a string.");if("string"!=typeof t)throw new TypeError("Secret string must be provided.");return e+"."+r.createHmac("sha256",t).update(e).digest("base64").replace(/\=+$/,"")},t.unsign=function(e,n){if("string"!=typeof e)throw new TypeError("Signed cookie string must be provided.");if("string"!=typeof n)throw new TypeError("Secret string must be provided.");var r=e.slice(0,e.lastIndexOf("."));return a(t.sign(r,n))==a(e)&&r}},6489:(e,t)=>{"use strict";t.parse=function(e,t){if("string"!=typeof e)throw new TypeError("argument str must be a string");for(var n={},r=(t||{}).decode||a,o=0;o{var r=n(614),a=n(6330),o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not a function")}},9483:(e,t,n)=>{var r=n(4411),a=n(6330),o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not a constructor")}},6077:(e,t,n)=>{var r=n(614),a=String,o=TypeError;e.exports=function(e){if("object"==typeof e||r(e))return e;throw o("Can't set "+a(e)+" as a prototype")}},1223:(e,t,n)=>{var r=n(5112),a=n(30),o=n(3070).f,i=r("unscopables"),s=Array.prototype;null==s[i]&&o(s,i,{configurable:!0,value:a(null)}),e.exports=function(e){s[i][e]=!0}},1530:(e,t,n)=>{"use strict";var r=n(8710).charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},5787:(e,t,n)=>{var r=n(7976),a=TypeError;e.exports=function(e,t){if(r(t,e))return e;throw a("Incorrect invocation")}},9670:(e,t,n)=>{var r=n(111),a=String,o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not an object")}},8533:(e,t,n)=>{"use strict";var r=n(2092).forEach,a=n(9341)("forEach");e.exports=a?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},8457:(e,t,n)=>{"use strict";var r=n(9974),a=n(6916),o=n(7908),i=n(3411),s=n(7659),c=n(4411),u=n(6244),p=n(6135),l=n(4121),d=n(1246),f=Array;e.exports=function(e){var t=o(e),n=c(this),m=arguments.length,v=m>1?arguments[1]:void 0,h=void 0!==v;h&&(v=r(v,m>2?arguments[2]:void 0));var b,g,y,x,w,_,S=d(t),k=0;if(!S||this===f&&s(S))for(b=u(t),g=n?new this(b):f(b);b>k;k++)_=h?v(t[k],k):t[k],p(g,k,_);else for(w=(x=l(t,S)).next,g=n?new this:[];!(y=a(w,x)).done;k++)_=h?i(x,v,[y.value,k],!0):y.value,p(g,k,_);return g.length=k,g}},1318:(e,t,n)=>{var r=n(5656),a=n(1400),o=n(6244),i=function(e){return function(t,n,i){var s,c=r(t),u=o(c),p=a(i,u);if(e&&n!=n){for(;u>p;)if((s=c[p++])!=s)return!0}else for(;u>p;p++)if((e||p in c)&&c[p]===n)return e||p||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},2092:(e,t,n)=>{var r=n(9974),a=n(1702),o=n(8361),i=n(7908),s=n(6244),c=n(5417),u=a([].push),p=function(e){var t=1==e,n=2==e,a=3==e,p=4==e,l=6==e,d=7==e,f=5==e||l;return function(m,v,h,b){for(var g,y,x=i(m),w=o(x),_=r(v,h),S=s(w),k=0,E=b||c,A=t?E(m,S):n||d?E(m,0):void 0;S>k;k++)if((f||k in w)&&(y=_(g=w[k],k,x),e))if(t)A[k]=y;else if(y)switch(e){case 3:return!0;case 5:return g;case 6:return k;case 2:u(A,g)}else switch(e){case 4:return!1;case 7:u(A,g)}return l?-1:a||p?p:A}};e.exports={forEach:p(0),map:p(1),filter:p(2),some:p(3),every:p(4),find:p(5),findIndex:p(6),filterReject:p(7)}},1194:(e,t,n)=>{var r=n(7293),a=n(5112),o=n(7392),i=a("species");e.exports=function(e){return o>=51||!r((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},9341:(e,t,n)=>{"use strict";var r=n(7293);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){return 1},1)}))}},3671:(e,t,n)=>{var r=n(9662),a=n(7908),o=n(8361),i=n(6244),s=TypeError,c=function(e){return function(t,n,c,u){r(n);var p=a(t),l=o(p),d=i(p),f=e?d-1:0,m=e?-1:1;if(c<2)for(;;){if(f in l){u=l[f],f+=m;break}if(f+=m,e?f<0:d<=f)throw s("Reduce of empty array with no initial value")}for(;e?f>=0:d>f;f+=m)f in l&&(u=n(u,l[f],f,p));return u}};e.exports={left:c(!1),right:c(!0)}},1589:(e,t,n)=>{var r=n(1400),a=n(6244),o=n(6135),i=Array,s=Math.max;e.exports=function(e,t,n){for(var c=a(e),u=r(t,c),p=r(void 0===n?c:n,c),l=i(s(p-u,0)),d=0;u{var r=n(1702);e.exports=r([].slice)},4362:(e,t,n)=>{var r=n(1589),a=Math.floor,o=function(e,t){var n=e.length,c=a(n/2);return n<8?i(e,t):s(e,o(r(e,0,c),t),o(r(e,c),t),t)},i=function(e,t){for(var n,r,a=e.length,o=1;o0;)e[r]=e[--r];r!==o++&&(e[r]=n)}return e},s=function(e,t,n,r){for(var a=t.length,o=n.length,i=0,s=0;i{var r=n(3157),a=n(4411),o=n(111),i=n(5112)("species"),s=Array;e.exports=function(e){var t;return r(e)&&(t=e.constructor,(a(t)&&(t===s||r(t.prototype))||o(t)&&null===(t=t[i]))&&(t=void 0)),void 0===t?s:t}},5417:(e,t,n)=>{var r=n(7475);e.exports=function(e,t){return new(r(e))(0===t?0:t)}},3411:(e,t,n)=>{var r=n(9670),a=n(9212);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){a(e,"throw",t)}}},7072:(e,t,n)=>{var r=n(5112)("iterator"),a=!1;try{var o=0,i={next:function(){return{done:!!o++}},return:function(){a=!0}};i[r]=function(){return this},Array.from(i,(function(){throw 2}))}catch(e){}e.exports=function(e,t){if(!t&&!a)return!1;var n=!1;try{var o={};o[r]=function(){return{next:function(){return{done:n=!0}}}},e(o)}catch(e){}return n}},4326:(e,t,n)=>{var r=n(1702),a=r({}.toString),o=r("".slice);e.exports=function(e){return o(a(e),8,-1)}},648:(e,t,n)=>{var r=n(1694),a=n(614),o=n(4326),i=n(5112)("toStringTag"),s=Object,c="Arguments"==o(function(){return arguments}());e.exports=r?o:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=s(e),i))?n:c?o(t):"Object"==(r=o(t))&&a(t.callee)?"Arguments":r}},9920:(e,t,n)=>{var r=n(2597),a=n(3887),o=n(1236),i=n(3070);e.exports=function(e,t,n){for(var s=a(t),c=i.f,u=o.f,p=0;p{var r=n(5112)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,"/./"[e](t)}catch(e){}}return!1}},8544:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},6178:e=>{e.exports=function(e,t){return{value:e,done:t}}},8880:(e,t,n)=>{var r=n(9781),a=n(3070),o=n(9114);e.exports=r?function(e,t,n){return a.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},9114:e=>{e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},6135:(e,t,n)=>{"use strict";var r=n(4948),a=n(3070),o=n(9114);e.exports=function(e,t,n){var i=r(t);i in e?a.f(e,i,o(0,n)):e[i]=n}},7045:(e,t,n)=>{var r=n(6339),a=n(3070);e.exports=function(e,t,n){return n.get&&r(n.get,t,{getter:!0}),n.set&&r(n.set,t,{setter:!0}),a.f(e,t,n)}},8052:(e,t,n)=>{var r=n(614),a=n(3070),o=n(6339),i=n(3072);e.exports=function(e,t,n,s){s||(s={});var c=s.enumerable,u=void 0!==s.name?s.name:t;if(r(n)&&o(n,u,s),s.global)c?e[t]=n:i(t,n);else{try{s.unsafe?e[t]&&(c=!0):delete e[t]}catch(e){}c?e[t]=n:a.f(e,t,{value:n,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return e}},3072:(e,t,n)=>{var r=n(7854),a=Object.defineProperty;e.exports=function(e,t){try{a(r,e,{value:t,configurable:!0,writable:!0})}catch(n){r[e]=t}return t}},5117:(e,t,n)=>{"use strict";var r=n(6330),a=TypeError;e.exports=function(e,t){if(!delete e[t])throw a("Cannot delete property "+r(t)+" of "+r(e))}},9781:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},4154:e=>{var t="object"==typeof document&&document.all,n=void 0===t&&void 0!==t;e.exports={all:t,IS_HTMLDDA:n}},317:(e,t,n)=>{var r=n(7854),a=n(111),o=r.document,i=a(o)&&a(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},7207:e=>{var t=TypeError;e.exports=function(e){if(e>9007199254740991)throw t("Maximum allowed index exceeded");return e}},8324:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(e,t,n)=>{var r=n(317)("span").classList,a=r&&r.constructor&&r.constructor.prototype;e.exports=a===Object.prototype?void 0:a},8886:(e,t,n)=>{var r=n(8113).match(/firefox\/(\d+)/i);e.exports=!!r&&+r[1]},7871:(e,t,n)=>{var r=n(3823),a=n(5268);e.exports=!r&&!a&&"object"==typeof window&&"object"==typeof document},3823:e=>{e.exports="object"==typeof Deno&&Deno&&"object"==typeof Deno.version},256:(e,t,n)=>{var r=n(8113);e.exports=/MSIE|Trident/.test(r)},1528:(e,t,n)=>{var r=n(8113);e.exports=/ipad|iphone|ipod/i.test(r)&&"undefined"!=typeof Pebble},6833:(e,t,n)=>{var r=n(8113);e.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(r)},5268:(e,t,n)=>{var r=n(4326);e.exports="undefined"!=typeof process&&"process"==r(process)},1036:(e,t,n)=>{var r=n(8113);e.exports=/web0s(?!.*chrome)/i.test(r)},8113:e=>{e.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},7392:(e,t,n)=>{var r,a,o=n(7854),i=n(8113),s=o.process,c=o.Deno,u=s&&s.versions||c&&c.version,p=u&&u.v8;p&&(a=(r=p.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!a&&i&&(!(r=i.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=i.match(/Chrome\/(\d+)/))&&(a=+r[1]),e.exports=a},8008:(e,t,n)=>{var r=n(8113).match(/AppleWebKit\/(\d+)\./);e.exports=!!r&&+r[1]},748:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:(e,t,n)=>{var r=n(7854),a=n(1236).f,o=n(8880),i=n(8052),s=n(3072),c=n(9920),u=n(4705);e.exports=function(e,t){var n,p,l,d,f,m=e.target,v=e.global,h=e.stat;if(n=v?r:h?r[m]||s(m,{}):(r[m]||{}).prototype)for(p in t){if(d=t[p],l=e.dontCallGetSet?(f=a(n,p))&&f.value:n[p],!u(v?p:m+(h?".":"#")+p,e.forced)&&void 0!==l){if(typeof d==typeof l)continue;c(d,l)}(e.sham||l&&l.sham)&&o(d,"sham",!0),i(n,p,d,e)}}},7293:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},7007:(e,t,n)=>{"use strict";n(4916);var r=n(1470),a=n(8052),o=n(2261),i=n(7293),s=n(5112),c=n(8880),u=s("species"),p=RegExp.prototype;e.exports=function(e,t,n,l){var d=s(e),f=!i((function(){var t={};return t[d]=function(){return 7},7!=""[e](t)})),m=f&&!i((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[u]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return t=!0,null},n[d](""),!t}));if(!f||!m||n){var v=r(/./[d]),h=t(d,""[e],(function(e,t,n,a,i){var s=r(e),c=t.exec;return c===o||c===p.exec?f&&!i?{done:!0,value:v(t,n,a)}:{done:!0,value:s(n,t,a)}:{done:!1}}));a(String.prototype,e,h[0]),a(p,d,h[1])}l&&c(p[d],"sham",!0)}},2104:(e,t,n)=>{var r=n(4374),a=Function.prototype,o=a.apply,i=a.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?i.bind(o):function(){return i.apply(o,arguments)})},9974:(e,t,n)=>{var r=n(1470),a=n(9662),o=n(4374),i=r(r.bind);e.exports=function(e,t){return a(e),void 0===t?e:o?i(e,t):function(){return e.apply(t,arguments)}}},4374:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")}))},7065:(e,t,n)=>{"use strict";var r=n(1702),a=n(9662),o=n(111),i=n(2597),s=n(206),c=n(4374),u=Function,p=r([].concat),l=r([].join),d={},f=function(e,t,n){if(!i(d,t)){for(var r=[],a=0;a{var r=n(4374),a=Function.prototype.call;e.exports=r?a.bind(a):function(){return a.apply(a,arguments)}},6530:(e,t,n)=>{var r=n(9781),a=n(2597),o=Function.prototype,i=r&&Object.getOwnPropertyDescriptor,s=a(o,"name"),c=s&&"something"===function(){}.name,u=s&&(!r||r&&i(o,"name").configurable);e.exports={EXISTS:s,PROPER:c,CONFIGURABLE:u}},5668:(e,t,n)=>{var r=n(1702),a=n(9662);e.exports=function(e,t,n){try{return r(a(Object.getOwnPropertyDescriptor(e,t)[n]))}catch(e){}}},1470:(e,t,n)=>{var r=n(4326),a=n(1702);e.exports=function(e){if("Function"===r(e))return a(e)}},1702:(e,t,n)=>{var r=n(4374),a=Function.prototype,o=a.call,i=r&&a.bind.bind(o,o);e.exports=r?i:function(e){return function(){return o.apply(e,arguments)}}},5005:(e,t,n)=>{var r=n(7854),a=n(614),o=function(e){return a(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?o(r[e]):r[e]&&r[e][t]}},1246:(e,t,n)=>{var r=n(648),a=n(8173),o=n(8554),i=n(7497),s=n(5112)("iterator");e.exports=function(e){if(!o(e))return a(e,s)||a(e,"@@iterator")||i[r(e)]}},4121:(e,t,n)=>{var r=n(6916),a=n(9662),o=n(9670),i=n(6330),s=n(1246),c=TypeError;e.exports=function(e,t){var n=arguments.length<2?s(e):t;if(a(n))return o(r(n,e));throw c(i(e)+" is not iterable")}},8044:(e,t,n)=>{var r=n(1702),a=n(3157),o=n(614),i=n(4326),s=n(1340),c=r([].push);e.exports=function(e){if(o(e))return e;if(a(e)){for(var t=e.length,n=[],r=0;r{var r=n(9662),a=n(8554);e.exports=function(e,t){var n=e[t];return a(n)?void 0:r(n)}},647:(e,t,n)=>{var r=n(1702),a=n(7908),o=Math.floor,i=r("".charAt),s=r("".replace),c=r("".slice),u=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,p=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,t,n,r,l,d){var f=n+e.length,m=r.length,v=p;return void 0!==l&&(l=a(l),v=u),s(d,v,(function(a,s){var u;switch(i(s,0)){case"$":return"$";case"&":return e;case"`":return c(t,0,n);case"'":return c(t,f);case"<":u=l[c(s,1,-1)];break;default:var p=+s;if(0===p)return a;if(p>m){var d=o(p/10);return 0===d?a:d<=m?void 0===r[d-1]?i(s,1):r[d-1]+i(s,1):a}u=r[p-1]}return void 0===u?"":u}))}},7854:e=>{var t=function(e){return e&&e.Math==Math&&e};e.exports=t("object"==typeof globalThis&&globalThis)||t("object"==typeof window&&window)||t("object"==typeof self&&self)||t("object"==typeof global&&global)||function(){return this}()||Function("return this")()},2597:(e,t,n)=>{var r=n(1702),a=n(7908),o=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return o(a(e),t)}},3501:e=>{e.exports={}},842:e=>{e.exports=function(e,t){try{1==arguments.length?console.error(e):console.error(e,t)}catch(e){}}},490:(e,t,n)=>{var r=n(5005);e.exports=r("document","documentElement")},4664:(e,t,n)=>{var r=n(9781),a=n(7293),o=n(317);e.exports=!r&&!a((function(){return 7!=Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a}))},8361:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(4326),i=Object,s=r("".split);e.exports=a((function(){return!i("z").propertyIsEnumerable(0)}))?function(e){return"String"==o(e)?s(e,""):i(e)}:i},9587:(e,t,n)=>{var r=n(614),a=n(111),o=n(7674);e.exports=function(e,t,n){var i,s;return o&&r(i=t.constructor)&&i!==n&&a(s=i.prototype)&&s!==n.prototype&&o(e,s),e}},2788:(e,t,n)=>{var r=n(1702),a=n(614),o=n(5465),i=r(Function.toString);a(o.inspectSource)||(o.inspectSource=function(e){return i(e)}),e.exports=o.inspectSource},9909:(e,t,n)=>{var r,a,o,i=n(4811),s=n(7854),c=n(111),u=n(8880),p=n(2597),l=n(5465),d=n(6200),f=n(3501),m="Object already initialized",v=s.TypeError,h=s.WeakMap;if(i||l.state){var b=l.state||(l.state=new h);b.get=b.get,b.has=b.has,b.set=b.set,r=function(e,t){if(b.has(e))throw v(m);return t.facade=e,b.set(e,t),t},a=function(e){return b.get(e)||{}},o=function(e){return b.has(e)}}else{var g=d("state");f[g]=!0,r=function(e,t){if(p(e,g))throw v(m);return t.facade=e,u(e,g,t),t},a=function(e){return p(e,g)?e[g]:{}},o=function(e){return p(e,g)}}e.exports={set:r,get:a,has:o,enforce:function(e){return o(e)?a(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!c(t)||(n=a(t)).type!==e)throw v("Incompatible receiver, "+e+" required");return n}}}},7659:(e,t,n)=>{var r=n(5112),a=n(7497),o=r("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(a.Array===e||i[o]===e)}},3157:(e,t,n)=>{var r=n(4326);e.exports=Array.isArray||function(e){return"Array"==r(e)}},614:(e,t,n)=>{var r=n(4154),a=r.all;e.exports=r.IS_HTMLDDA?function(e){return"function"==typeof e||e===a}:function(e){return"function"==typeof e}},4411:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(614),i=n(648),s=n(5005),c=n(2788),u=function(){},p=[],l=s("Reflect","construct"),d=/^\s*(?:class|function)\b/,f=r(d.exec),m=!d.exec(u),v=function(e){if(!o(e))return!1;try{return l(u,p,e),!0}catch(e){return!1}},h=function(e){if(!o(e))return!1;switch(i(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return m||!!f(d,c(e))}catch(e){return!0}};h.sham=!0,e.exports=!l||a((function(){var e;return v(v.call)||!v(Object)||!v((function(){e=!0}))||e}))?h:v},4705:(e,t,n)=>{var r=n(7293),a=n(614),o=/#|\.prototype\./,i=function(e,t){var n=c[s(e)];return n==p||n!=u&&(a(t)?r(t):!!t)},s=i.normalize=function(e){return String(e).replace(o,".").toLowerCase()},c=i.data={},u=i.NATIVE="N",p=i.POLYFILL="P";e.exports=i},5988:(e,t,n)=>{var r=n(111),a=Math.floor;e.exports=Number.isInteger||function(e){return!r(e)&&isFinite(e)&&a(e)===e}},8554:e=>{e.exports=function(e){return null==e}},111:(e,t,n)=>{var r=n(614),a=n(4154),o=a.all;e.exports=a.IS_HTMLDDA?function(e){return"object"==typeof e?null!==e:r(e)||e===o}:function(e){return"object"==typeof e?null!==e:r(e)}},1913:e=>{e.exports=!1},7850:(e,t,n)=>{var r=n(111),a=n(4326),o=n(5112)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[o])?!!t:"RegExp"==a(e))}},2190:(e,t,n)=>{var r=n(5005),a=n(614),o=n(7976),i=n(3307),s=Object;e.exports=i?function(e){return"symbol"==typeof e}:function(e){var t=r("Symbol");return a(t)&&o(t.prototype,s(e))}},408:(e,t,n)=>{var r=n(9974),a=n(6916),o=n(9670),i=n(6330),s=n(7659),c=n(6244),u=n(7976),p=n(4121),l=n(1246),d=n(9212),f=TypeError,m=function(e,t){this.stopped=e,this.result=t},v=m.prototype;e.exports=function(e,t,n){var h,b,g,y,x,w,_,S=n&&n.that,k=!(!n||!n.AS_ENTRIES),E=!(!n||!n.IS_RECORD),A=!(!n||!n.IS_ITERATOR),j=!(!n||!n.INTERRUPTED),O=r(t,S),C=function(e){return h&&d(h,"normal",e),new m(!0,e)},R=function(e){return k?(o(e),j?O(e[0],e[1],C):O(e[0],e[1])):j?O(e,C):O(e)};if(E)h=e.iterator;else if(A)h=e;else{if(!(b=l(e)))throw f(i(e)+" is not iterable");if(s(b)){for(g=0,y=c(e);y>g;g++)if((x=R(e[g]))&&u(v,x))return x;return new m(!1)}h=p(e,b)}for(w=E?e.next:h.next;!(_=a(w,h)).done;){try{x=R(_.value)}catch(e){d(h,"throw",e)}if("object"==typeof x&&x&&u(v,x))return x}return new m(!1)}},9212:(e,t,n)=>{var r=n(6916),a=n(9670),o=n(8173);e.exports=function(e,t,n){var i,s;a(e);try{if(!(i=o(e,"return"))){if("throw"===t)throw n;return n}i=r(i,e)}catch(e){s=!0,i=e}if("throw"===t)throw n;if(s)throw i;return a(i),n}},3061:(e,t,n)=>{"use strict";var r=n(3383).IteratorPrototype,a=n(30),o=n(9114),i=n(8003),s=n(7497),c=function(){return this};e.exports=function(e,t,n,u){var p=t+" Iterator";return e.prototype=a(r,{next:o(+!u,n)}),i(e,p,!1,!0),s[p]=c,e}},1656:(e,t,n)=>{"use strict";var r=n(2109),a=n(6916),o=n(1913),i=n(6530),s=n(614),c=n(3061),u=n(9518),p=n(7674),l=n(8003),d=n(8880),f=n(8052),m=n(5112),v=n(7497),h=n(3383),b=i.PROPER,g=i.CONFIGURABLE,y=h.IteratorPrototype,x=h.BUGGY_SAFARI_ITERATORS,w=m("iterator"),_="keys",S="values",k="entries",E=function(){return this};e.exports=function(e,t,n,i,m,h,A){c(n,t,i);var j,O,C,R=function(e){if(e===m&&N)return N;if(!x&&e in P)return P[e];switch(e){case _:case S:case k:return function(){return new n(this,e)}}return function(){return new n(this)}},T=t+" Iterator",I=!1,P=e.prototype,U=P[w]||P["@@iterator"]||m&&P[m],N=!x&&U||R(m),D="Array"==t&&P.entries||U;if(D&&(j=u(D.call(new e)))!==Object.prototype&&j.next&&(o||u(j)===y||(p?p(j,y):s(j[w])||f(j,w,E)),l(j,T,!0,!0),o&&(v[T]=E)),b&&m==S&&U&&U.name!==S&&(!o&&g?d(P,"name",S):(I=!0,N=function(){return a(U,this)})),m)if(O={values:R(S),keys:h?N:R(_),entries:R(k)},A)for(C in O)(x||I||!(C in P))&&f(P,C,O[C]);else r({target:t,proto:!0,forced:x||I},O);return o&&!A||P[w]===N||f(P,w,N,{name:m}),v[t]=N,O}},3383:(e,t,n)=>{"use strict";var r,a,o,i=n(7293),s=n(614),c=n(111),u=n(30),p=n(9518),l=n(8052),d=n(5112),f=n(1913),m=d("iterator"),v=!1;[].keys&&("next"in(o=[].keys())?(a=p(p(o)))!==Object.prototype&&(r=a):v=!0),!c(r)||i((function(){var e={};return r[m].call(e)!==e}))?r={}:f&&(r=u(r)),s(r[m])||l(r,m,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:v}},7497:e=>{e.exports={}},6244:(e,t,n)=>{var r=n(7466);e.exports=function(e){return r(e.length)}},6339:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(614),i=n(2597),s=n(9781),c=n(6530).CONFIGURABLE,u=n(2788),p=n(9909),l=p.enforce,d=p.get,f=String,m=Object.defineProperty,v=r("".slice),h=r("".replace),b=r([].join),g=s&&!a((function(){return 8!==m((function(){}),"length",{value:8}).length})),y=String(String).split("String"),x=e.exports=function(e,t,n){"Symbol("===v(f(t),0,7)&&(t="["+h(f(t),/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(t="get "+t),n&&n.setter&&(t="set "+t),(!i(e,"name")||c&&e.name!==t)&&(s?m(e,"name",{value:t,configurable:!0}):e.name=t),g&&n&&i(n,"arity")&&e.length!==n.arity&&m(e,"length",{value:n.arity});try{n&&i(n,"constructor")&&n.constructor?s&&m(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(e){}var r=l(e);return i(r,"source")||(r.source=b(y,"string"==typeof t?t:"")),e};Function.prototype.toString=x((function(){return o(this)&&d(this).source||u(this)}),"toString")},4758:e=>{var t=Math.ceil,n=Math.floor;e.exports=Math.trunc||function(e){var r=+e;return(r>0?n:t)(r)}},5948:(e,t,n)=>{var r,a,o,i,s,c=n(7854),u=n(9974),p=n(1236).f,l=n(261).set,d=n(8572),f=n(6833),m=n(1528),v=n(1036),h=n(5268),b=c.MutationObserver||c.WebKitMutationObserver,g=c.document,y=c.process,x=c.Promise,w=p(c,"queueMicrotask"),_=w&&w.value;if(!_){var S=new d,k=function(){var e,t;for(h&&(e=y.domain)&&e.exit();t=S.get();)try{t()}catch(e){throw S.head&&r(),e}e&&e.enter()};f||h||v||!b||!g?!m&&x&&x.resolve?((i=x.resolve(void 0)).constructor=x,s=u(i.then,i),r=function(){s(k)}):h?r=function(){y.nextTick(k)}:(l=u(l,c),r=function(){l(k)}):(a=!0,o=g.createTextNode(""),new b(k).observe(o,{characterData:!0}),r=function(){o.data=a=!a}),_=function(e){S.head||r(),S.add(e)}}e.exports=_},8523:(e,t,n)=>{"use strict";var r=n(9662),a=TypeError,o=function(e){var t,n;this.promise=new e((function(e,r){if(void 0!==t||void 0!==n)throw a("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new o(e)}},3929:(e,t,n)=>{var r=n(7850),a=TypeError;e.exports=function(e){if(r(e))throw a("The method doesn't accept regular expressions");return e}},2814:(e,t,n)=>{var r=n(7854),a=n(7293),o=n(1702),i=n(1340),s=n(3111).trim,c=n(1361),u=o("".charAt),p=r.parseFloat,l=r.Symbol,d=l&&l.iterator,f=1/p(c+"-0")!=-1/0||d&&!a((function(){p(Object(d))}));e.exports=f?function(e){var t=s(i(e)),n=p(t);return 0===n&&"-"==u(t,0)?-0:n}:p},3009:(e,t,n)=>{var r=n(7854),a=n(7293),o=n(1702),i=n(1340),s=n(3111).trim,c=n(1361),u=r.parseInt,p=r.Symbol,l=p&&p.iterator,d=/^[+-]?0x/i,f=o(d.exec),m=8!==u(c+"08")||22!==u(c+"0x16")||l&&!a((function(){u(Object(l))}));e.exports=m?function(e,t){var n=s(i(e));return u(n,t>>>0||(f(d,n)?16:10))}:u},30:(e,t,n)=>{var r,a=n(9670),o=n(6048),i=n(748),s=n(3501),c=n(490),u=n(317),p=n(6200)("IE_PROTO"),l=function(){},d=function(e){return"