hybrid_platforms_conductor 32.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/check-node +24 -0
- data/bin/deploy +12 -0
- data/bin/dump_nodes_json +12 -0
- data/bin/free_ips +23 -0
- data/bin/free_veids +17 -0
- data/bin/get_impacted_nodes +43 -0
- data/bin/last_deploys +56 -0
- data/bin/nodes_to_deploy +104 -0
- data/bin/report +10 -0
- data/bin/run +39 -0
- data/bin/setup +11 -0
- data/bin/ssh_config +14 -0
- data/bin/test +13 -0
- data/bin/topograph +54 -0
- data/lib/hybrid_platforms_conductor/action.rb +82 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +307 -0
- data/lib/hybrid_platforms_conductor/bitbucket.rb +123 -0
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +188 -0
- data/lib/hybrid_platforms_conductor/cmdb.rb +34 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +78 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +43 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +110 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +38 -0
- data/lib/hybrid_platforms_conductor/config.rb +263 -0
- data/lib/hybrid_platforms_conductor/confluence.rb +119 -0
- data/lib/hybrid_platforms_conductor/connector.rb +84 -0
- data/lib/hybrid_platforms_conductor/credentials.rb +127 -0
- data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +42 -0
- data/lib/hybrid_platforms_conductor/deployer.rb +598 -0
- data/lib/hybrid_platforms_conductor/executable.rb +145 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/interactive.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/my_action.rb.sample +79 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +63 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/ruby.rb +69 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +61 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +78 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +104 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +114 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/my_cmdb.rb.sample +129 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +66 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +156 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +702 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +292 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +148 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/my_provisioner.rb.sample +103 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +125 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +522 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +707 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +122 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +69 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +164 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/my_report_plugin.rb.sample +88 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +61 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +33 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +137 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/can_be_checked.rb +21 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +112 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_from_scratch.rb +35 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +28 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_from_scratch.rb +36 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +49 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +25 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +45 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +45 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +25 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +77 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +56 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +54 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +47 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +82 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +120 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/my_test_plugin.rb.sample +143 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +74 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +85 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre-meltdown-checker.sh +1930 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +56 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +31 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +159 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +122 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/my_test_report.rb.sample +48 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +120 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_errors_status.html.erb +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_gauge.html.erb +49 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/confluence.html.erb +242 -0
- data/lib/hybrid_platforms_conductor/io_router.rb +70 -0
- data/lib/hybrid_platforms_conductor/json_dumper.rb +88 -0
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +319 -0
- data/lib/hybrid_platforms_conductor/mutex_dir +76 -0
- data/lib/hybrid_platforms_conductor/nodes_handler.rb +597 -0
- data/lib/hybrid_platforms_conductor/parallel_threads.rb +97 -0
- data/lib/hybrid_platforms_conductor/platform_handler.rb +188 -0
- data/lib/hybrid_platforms_conductor/platforms_handler.rb +118 -0
- data/lib/hybrid_platforms_conductor/plugin.rb +53 -0
- data/lib/hybrid_platforms_conductor/plugins.rb +101 -0
- data/lib/hybrid_platforms_conductor/provisioner.rb +181 -0
- data/lib/hybrid_platforms_conductor/report.rb +31 -0
- data/lib/hybrid_platforms_conductor/reports_handler.rb +84 -0
- data/lib/hybrid_platforms_conductor/services_handler.rb +274 -0
- data/lib/hybrid_platforms_conductor/test.rb +141 -0
- data/lib/hybrid_platforms_conductor/test_by_service.rb +22 -0
- data/lib/hybrid_platforms_conductor/test_report.rb +282 -0
- data/lib/hybrid_platforms_conductor/tests_runner.rb +590 -0
- data/lib/hybrid_platforms_conductor/thycotic.rb +92 -0
- data/lib/hybrid_platforms_conductor/topographer.rb +859 -0
- data/lib/hybrid_platforms_conductor/topographer/plugin.rb +20 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +127 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +72 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/my_topographer_output_plugin.rb.sample +37 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/svg.rb +30 -0
- data/lib/hybrid_platforms_conductor/version.rb +5 -0
- data/spec/hybrid_platforms_conductor_test.rb +159 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +43 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +18 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +102 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +108 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +79 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +199 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +212 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +125 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +448 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +313 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +32 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +134 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +256 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +338 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +101 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +165 -0
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +238 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +9 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +243 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +104 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +131 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker/Dockerfile +10 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker_spec.rb +123 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +211 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +126 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +290 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +43 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/proxmox.json +3 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +82 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +786 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +112 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +190 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +200 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +67 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +79 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +41 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +33 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +64 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +133 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +19 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +446 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +127 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +318 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +132 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +58 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +97 -0
- data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +104 -0
- data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +243 -0
- data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +44 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +121 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +142 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +101 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +388 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +274 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +264 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +194 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +37 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +194 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +137 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +257 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +110 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +367 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +111 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +29 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +166 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb2.rb +93 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others2.rb +58 -0
- data/spec/hybrid_platforms_conductor_test/executables/check-node_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +158 -0
- data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +173 -0
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +283 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +67 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +251 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +111 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +71 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +54 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +139 -0
- data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +173 -0
- data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +41 -0
- data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +98 -0
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +92 -0
- data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +37 -0
- data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +130 -0
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +149 -0
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +812 -0
- data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +96 -0
- data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/platform_handler_helpers.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +127 -0
- data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +48 -0
- data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +789 -0
- data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +29 -0
- data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +38 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id1.rb +22 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id2.rb +22 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/test_plugin_id3.rb +26 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type2/test_plugin_id4.rb +26 -0
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +225 -0
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test2.rb +11 -0
- data/spec/hybrid_platforms_conductor_test/report_plugin.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/test_action.rb +66 -0
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +151 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +53 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +47 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node_ssh.rb +42 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/test_provisioner.rb +95 -0
- data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +49 -0
- data/spec/spec_helper.rb +111 -0
- metadata +566 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'hybrid_platforms_conductor/provisioner'
|
3
|
+
|
4
|
+
module HybridPlatformsConductor
|
5
|
+
|
6
|
+
module HpcPlugins
|
7
|
+
|
8
|
+
module Provisioner
|
9
|
+
|
10
|
+
# Provision Podman containers
|
11
|
+
class Podman < HybridPlatformsConductor::Provisioner
|
12
|
+
|
13
|
+
# Create an instance.
|
14
|
+
# Reuse an existing one if it already exists.
|
15
|
+
# [API] - This method is mandatory
|
16
|
+
def create
|
17
|
+
# Get the image name for this node
|
18
|
+
image = @nodes_handler.get_image_of(@node).to_sym
|
19
|
+
# Find if we have such an image registered
|
20
|
+
if @config.known_os_images.include?(image)
|
21
|
+
# Build the image if it does not exist
|
22
|
+
image_tag = "hpc_image_#{image}"
|
23
|
+
image_futex_file = "#{Dir.tmpdir}/hpc_podman_image_futexes/#{image_tag}"
|
24
|
+
FileUtils.mkdir_p File.dirname(image_futex_file)
|
25
|
+
Futex.new(image_futex_file).open do
|
26
|
+
@cmd_runner.run_cmd "cd #{@config.os_image_dir(image)} && #{podman_cmd} build --tag #{image_tag} --security-opt seccomp=/usr/share/containers/seccomp.json --cgroup-manager=cgroupfs ."
|
27
|
+
end
|
28
|
+
container_name = "hpc_container_#{@node}_#{@environment}"
|
29
|
+
container_futex_file = "#{Dir.tmpdir}/hpc_podman_container_futexes/#{image_tag}"
|
30
|
+
FileUtils.mkdir_p File.dirname(container_futex_file)
|
31
|
+
Futex.new(container_futex_file).open do
|
32
|
+
_exit_status, stdout, _stderr = @cmd_runner.run_cmd "#{podman_cmd} container list --all | grep #{container_name}", expected_code: [0, 1]
|
33
|
+
existing_container = !stdout.strip.empty?
|
34
|
+
@cmd_runner.run_cmd "#{podman_cmd} container create --name #{container_name} #{image_tag}" unless existing_container
|
35
|
+
@container = container_name
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise "[ #{@node}/#{@environment} ] - Unknown OS image #{image} defined for node #{@node}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Start an instance
|
43
|
+
# Prerequisite: create has been called before
|
44
|
+
# [API] - This method is mandatory
|
45
|
+
def start
|
46
|
+
log_debug "[ #{@node}/#{@environment} ] - Start Podman Container #{@container} ..."
|
47
|
+
@cmd_runner.run_cmd "#{podman_cmd} container start --cgroup-manager=cgroupfs #{@container}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Stop an instance
|
51
|
+
# Prerequisite: create has been called before
|
52
|
+
# [API] - This method is mandatory
|
53
|
+
def stop
|
54
|
+
log_debug "[ #{@node}/#{@environment} ] - Stop Podman Container #{@container} ..."
|
55
|
+
@cmd_runner.run_cmd "#{podman_cmd} container stop #{@container}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Destroy an instance
|
59
|
+
# Prerequisite: create has been called before
|
60
|
+
# [API] - This method is mandatory
|
61
|
+
def destroy
|
62
|
+
log_debug "[ #{@node}/#{@environment} ] - Destroy Podman Container #{@container} ..."
|
63
|
+
@cmd_runner.run_cmd "#{podman_cmd} container rm #{@container}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the state of an instance
|
67
|
+
# [API] - This method is mandatory
|
68
|
+
#
|
69
|
+
# Result::
|
70
|
+
# * Symbol: The state the instance is in. Possible values are:
|
71
|
+
# * *:missing*: The instance does not exist
|
72
|
+
# * *:created*: The instance has been created but is not running
|
73
|
+
# * *:running*: The instance is running
|
74
|
+
# * *:exited*: The instance has run and is now stopped
|
75
|
+
# * *:error*: The instance is in error
|
76
|
+
def state
|
77
|
+
if !defined?(@container) || @container.nil?
|
78
|
+
:missing
|
79
|
+
else
|
80
|
+
begin
|
81
|
+
_exit_status, stdout, _stderr = @cmd_runner.run_cmd "#{podman_cmd} container inspect #{@container}"
|
82
|
+
status = JSON.parse(stdout).first['State']['Status'].to_sym
|
83
|
+
status = :created if status == :configured
|
84
|
+
status
|
85
|
+
rescue
|
86
|
+
log_warn "Error while reading state of Podman container #{@container}: #{$!}"
|
87
|
+
:error
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return the IP address of an instance.
|
93
|
+
# Prerequisite: create has been called before.
|
94
|
+
# [API] - This method is optional
|
95
|
+
#
|
96
|
+
# Result::
|
97
|
+
# * String or nil: The instance IP address, or nil if this information is not relevant
|
98
|
+
def ip
|
99
|
+
# Get its IP that could have changed upon restart
|
100
|
+
# cf https://github.com/moby/moby/issues/2801
|
101
|
+
# Make sure we refresh its info before querying it, as we could hit a cache of a previous IP.
|
102
|
+
_exit_status, stdout, _stderr = @cmd_runner.run_cmd "#{podman_cmd} container inspect #{@container} | grep IPAddress"
|
103
|
+
stdout.strip.match(/\d+\.\d+\.\d+\.\d+/)[0]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Get the Podman command.
|
109
|
+
# Handle sudo rights if needed.
|
110
|
+
# Keep a cache of it for performance.
|
111
|
+
#
|
112
|
+
# Result::
|
113
|
+
# * String: The Podman command
|
114
|
+
def podman_cmd
|
115
|
+
@podman_cmd = @cmd_runner.root? ? 'podman' : 'sudo podman' unless defined?(@podman_cmd)
|
116
|
+
@podman_cmd
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,522 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'proxmox'
|
3
|
+
require 'digest'
|
4
|
+
require 'hybrid_platforms_conductor/actions_executor'
|
5
|
+
require 'hybrid_platforms_conductor/provisioner'
|
6
|
+
|
7
|
+
module HybridPlatformsConductor
|
8
|
+
|
9
|
+
module HpcPlugins
|
10
|
+
|
11
|
+
module Provisioner
|
12
|
+
|
13
|
+
# Monkey patch some Proxmox methods
|
14
|
+
module ProxmoxPatches
|
15
|
+
|
16
|
+
include LoggerHelpers
|
17
|
+
|
18
|
+
attr_accessor *%i[logger logger_stderr]
|
19
|
+
|
20
|
+
def check_response(response)
|
21
|
+
log_debug "Response from Proxmox API: #{response}"
|
22
|
+
log_warn "Response from Proxmox API: #{response}" if response.code >= 400 && !log_debug?
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
::Proxmox::Proxmox.prepend ProxmoxPatches
|
28
|
+
|
29
|
+
# Decorate the DSL of platforms definitions
|
30
|
+
module PlatformsDSLProxmox
|
31
|
+
|
32
|
+
# Mixin initializer
|
33
|
+
def init_proxmox
|
34
|
+
# List of Proxmox servers info
|
35
|
+
# Array< Hash<Symbol,Object> >
|
36
|
+
@proxmox_servers = []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Register a Proxmox server
|
40
|
+
#
|
41
|
+
# Parameters::
|
42
|
+
# * *proxmox_info* (Hash<Symbol,Object>): Proxmox server configuration. See Provisioner::Proxmox#proxmox_test_info to know about the returned structure.
|
43
|
+
def proxmox(proxmox_info)
|
44
|
+
@proxmox_servers << proxmox_info
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return the list of Proxmox servers
|
48
|
+
#
|
49
|
+
# Result::
|
50
|
+
# * Array<Hash<Symbol,Object>>: The list of Proxmox servers. See Provisioner::Proxmox#proxmox_test_info to know about the returned structure.
|
51
|
+
def proxmox_servers
|
52
|
+
@proxmox_servers
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Provision Proxmox containers
|
58
|
+
class Proxmox < HybridPlatformsConductor::Provisioner
|
59
|
+
|
60
|
+
extend_config_dsl_with PlatformsDSLProxmox, :init_proxmox
|
61
|
+
|
62
|
+
class << self
|
63
|
+
attr_accessor :proxmox_waiter_files_mutex
|
64
|
+
end
|
65
|
+
@proxmox_waiter_files_mutex = Mutex.new
|
66
|
+
|
67
|
+
# Maximum size in chars of hostnames set in Proxmox
|
68
|
+
MAX_PROXMOX_HOSTNAME_SIZE = 64
|
69
|
+
|
70
|
+
# Create an instance.
|
71
|
+
# Reuse an existing one if it already exists.
|
72
|
+
# [API] - This method is mandatory
|
73
|
+
def create
|
74
|
+
# First check if we already have a test container that corresponds to this node and environment
|
75
|
+
@lxc_details = nil
|
76
|
+
with_proxmox do |proxmox|
|
77
|
+
proxmox.get('nodes').each do |node_info|
|
78
|
+
if proxmox_test_info[:test_config][:pve_nodes].include?(node_info['node']) && node_info['status'] == 'online'
|
79
|
+
proxmox.get("nodes/#{node_info['node']}/lxc").each do |lxc_info|
|
80
|
+
vm_id = Integer(lxc_info['vmid'])
|
81
|
+
if vm_id.between?(*proxmox_test_info[:test_config][:vm_ids_range])
|
82
|
+
# Check if the description contains our ID
|
83
|
+
lxc_config = proxmox.get("nodes/#{node_info['node']}/lxc/#{vm_id}/config")
|
84
|
+
vm_description_lines = (lxc_config['description'] || '').split("\n")
|
85
|
+
hpc_marker_idx = vm_description_lines.index('===== HPC info =====')
|
86
|
+
unless hpc_marker_idx.nil?
|
87
|
+
# Get the HPC info associated to this VM
|
88
|
+
# Hash<Symbol,String>
|
89
|
+
vm_hpc_info = Hash[vm_description_lines[hpc_marker_idx + 1..-1].map do |line|
|
90
|
+
property, value = line.split(': ')
|
91
|
+
[property.to_sym, value]
|
92
|
+
end]
|
93
|
+
if vm_hpc_info[:node] == @node && vm_hpc_info[:environment] == @environment
|
94
|
+
# Found it
|
95
|
+
# Get back the IP
|
96
|
+
ip_found = nil
|
97
|
+
lxc_config['net0'].split(',').each do |net_info|
|
98
|
+
property, value = net_info.split('=')
|
99
|
+
if property == 'ip'
|
100
|
+
ip_found = value.split('/').first
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
raise "[ #{@node}/#{@environment} ] - Unable to get IP back from LXC container nodes/#{node_info['node']}/lxc/#{vm_id}/config" if ip_found.nil?
|
105
|
+
@lxc_details = {
|
106
|
+
pve_node: node_info['node'],
|
107
|
+
vm_id: vm_id,
|
108
|
+
vm_ip: ip_found
|
109
|
+
}
|
110
|
+
break
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
break if @lxc_details
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
unless @lxc_details
|
120
|
+
# We couldn't find an existing LXC container for this node/environment.
|
121
|
+
# We have to create one.
|
122
|
+
# Get the image name for this node
|
123
|
+
image = @nodes_handler.get_image_of(@node).to_sym
|
124
|
+
# Find if we have such an image registered
|
125
|
+
if @config.known_os_images.include?(image)
|
126
|
+
proxmox_conf = "#{@config.os_image_dir(image)}/proxmox.json"
|
127
|
+
if File.exist?(proxmox_conf)
|
128
|
+
pve_template = JSON.parse(File.read(proxmox_conf)).dig 'template'
|
129
|
+
if pve_template
|
130
|
+
# Query the inventory to know about minimum resources needed to deploy the node.
|
131
|
+
# Provide default values if they are not part of the metadata.
|
132
|
+
min_resources_to_deploy = {
|
133
|
+
cpus: 2,
|
134
|
+
ram_mb: 1024,
|
135
|
+
disk_gb: 10
|
136
|
+
}.merge(@nodes_handler.get_deploy_resources_min_of(@node) || {})
|
137
|
+
# Create the Proxmox container from the sync node.
|
138
|
+
vm_config = proxmox_test_info[:vm_config]
|
139
|
+
# Hostname in Proxmox is capped at 65 chars.
|
140
|
+
# Make sure we don't get over it, but still use a unique one.
|
141
|
+
hostname = "#{@node}.#{@environment}.hpc-test.com"
|
142
|
+
if hostname.size > MAX_PROXMOX_HOSTNAME_SIZE
|
143
|
+
# Truncate it, but add a unique ID in it.
|
144
|
+
# In the end the hostname looks like:
|
145
|
+
# <truncated_node_environment>.<unique_id>.hpc-test.com
|
146
|
+
hostname = "-#{Digest::MD5.hexdigest(hostname)[0..7]}.hpc-test.com"
|
147
|
+
hostname = "#{@node}.#{@environment}"[0..MAX_PROXMOX_HOSTNAME_SIZE - hostname.size - 1] + hostname
|
148
|
+
end
|
149
|
+
@lxc_details = request_lxc_creation_for( {
|
150
|
+
ostemplate: pve_template,
|
151
|
+
hostname: hostname.gsub('_', '-'),
|
152
|
+
cores: min_resources_to_deploy[:cpus],
|
153
|
+
cpulimit: min_resources_to_deploy[:cpus],
|
154
|
+
memory: min_resources_to_deploy[:ram_mb],
|
155
|
+
rootfs: "local-lvm:#{min_resources_to_deploy[:disk_gb]}",
|
156
|
+
nameserver: vm_config[:vm_dns_servers].join(' '),
|
157
|
+
searchdomain: vm_config[:vm_search_domain],
|
158
|
+
net0: "name=eth0,bridge=vmbr0,gw=#{vm_config[:vm_gateway]}",
|
159
|
+
password: 'root_pwd',
|
160
|
+
description: <<~EOS
|
161
|
+
===== HPC info =====
|
162
|
+
node: #{@node}
|
163
|
+
environment: #{@environment}
|
164
|
+
debug: #{log_debug? ? 'true' : 'false'}
|
165
|
+
EOS
|
166
|
+
})
|
167
|
+
else
|
168
|
+
raise "[ #{@node}/#{@environment} ] - No template found in #{proxmox_conf}"
|
169
|
+
end
|
170
|
+
else
|
171
|
+
raise "[ #{@node}/#{@environment} ] - No Proxmox configuration found at #{proxmox_conf}"
|
172
|
+
end
|
173
|
+
else
|
174
|
+
raise "[ #{@node}/#{@environment} ] - Unknown OS image #{image} defined for node #{@node}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Start an instance
|
180
|
+
# Prerequisite: create has been called before
|
181
|
+
# [API] - This method is mandatory
|
182
|
+
def start
|
183
|
+
log_debug "[ #{@node}/#{@environment} ] - Start Proxmox LXC Container ..."
|
184
|
+
with_proxmox do |proxmox|
|
185
|
+
run_proxmox_task(proxmox, :post, @lxc_details[:pve_node], "lxc/#{@lxc_details[:vm_id]}/status/start")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Stop an instance
|
190
|
+
# Prerequisite: create has been called before
|
191
|
+
# [API] - This method is mandatory
|
192
|
+
def stop
|
193
|
+
log_debug "[ #{@node}/#{@environment} ] - Stop Proxmox LXC Container ..."
|
194
|
+
with_proxmox do |proxmox|
|
195
|
+
run_proxmox_task(proxmox, :post, @lxc_details[:pve_node], "lxc/#{@lxc_details[:vm_id]}/status/stop")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Destroy an instance
|
200
|
+
# Prerequisite: create has been called before
|
201
|
+
# [API] - This method is mandatory
|
202
|
+
def destroy
|
203
|
+
log_debug "[ #{@node}/#{@environment} ] - Delete Proxmox LXC Container ..."
|
204
|
+
release_lxc_container(@lxc_details[:vm_id])
|
205
|
+
end
|
206
|
+
|
207
|
+
# Return the state of an instance
|
208
|
+
# [API] - This method is mandatory
|
209
|
+
#
|
210
|
+
# Result::
|
211
|
+
# * Symbol: The state the instance is in. Possible values are:
|
212
|
+
# * *:missing*: The instance does not exist
|
213
|
+
# * *:created*: The instance has been created but is not running
|
214
|
+
# * *:running*: The instance is running
|
215
|
+
# * *:exited*: The instance has run and is now stopped
|
216
|
+
# * *:error*: The instance is in error
|
217
|
+
def state
|
218
|
+
if @lxc_details.nil?
|
219
|
+
:missing
|
220
|
+
else
|
221
|
+
status = nil
|
222
|
+
with_proxmox do |proxmox|
|
223
|
+
vm_id_str = @lxc_details[:vm_id].to_s
|
224
|
+
status =
|
225
|
+
if proxmox.get("nodes/#{@lxc_details[:pve_node]}/lxc").any? { |data_info| data_info['vmid'] == vm_id_str }
|
226
|
+
status_info = proxmox.get("nodes/#{@lxc_details[:pve_node]}/lxc/#{@lxc_details[:vm_id]}/status/current")
|
227
|
+
# Careful that it is possible that somebody destroyed the VM and so its status is missing
|
228
|
+
status = status_info.key?('status') ? status_info['status'].to_sym : :missing
|
229
|
+
status = :exited if status == :stopped
|
230
|
+
status
|
231
|
+
else
|
232
|
+
:missing
|
233
|
+
end
|
234
|
+
end
|
235
|
+
status
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Return the IP address of an instance.
|
240
|
+
# Prerequisite: create has been called before.
|
241
|
+
# [API] - This method is optional
|
242
|
+
#
|
243
|
+
# Result::
|
244
|
+
# * String or nil: The instance IP address, or nil if this information is not relevant
|
245
|
+
def ip
|
246
|
+
@lxc_details[:vm_ip]
|
247
|
+
end
|
248
|
+
|
249
|
+
# Return the default timeout to apply when waiting for an instance to be started/stopped...
|
250
|
+
# [API] - This method is optional
|
251
|
+
#
|
252
|
+
# Result::
|
253
|
+
# * Integer: The timeout in seconds
|
254
|
+
def default_timeout
|
255
|
+
proxmox_test_info[:default_timeout] || 3600
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
# Connect to the Proxmox API
|
261
|
+
#
|
262
|
+
# Parameters::
|
263
|
+
# * Proc: Client code to be called when connected
|
264
|
+
# * Parameters::
|
265
|
+
# * *proxmox* (Proxmox): The Proxmox instance
|
266
|
+
def with_proxmox
|
267
|
+
url = proxmox_test_info[:api_url]
|
268
|
+
raise 'No Proxmox server defined' if url.nil?
|
269
|
+
Credentials.with_credentials_for(:proxmox, @logger, @logger_stderr, url: url) do |user, password|
|
270
|
+
log_debug "[ #{@node}/#{@environment} ] - Connect to Proxmox #{url}"
|
271
|
+
proxmox_logs = StringIO.new
|
272
|
+
proxmox = ::Proxmox::Proxmox.new(
|
273
|
+
"#{url}/api2/json/",
|
274
|
+
# Proxmox uses the hostname as the node name so make the default API node derived from the URL.
|
275
|
+
# cf https://pve.proxmox.com/wiki/Renaming_a_PVE_node
|
276
|
+
URI.parse(url).host.downcase.split('.').first,
|
277
|
+
user,
|
278
|
+
password,
|
279
|
+
ENV['hpc_realm_for_proxmox'] || 'pam',
|
280
|
+
{
|
281
|
+
verify_ssl: false,
|
282
|
+
log: Logger.new(proxmox_logs)
|
283
|
+
}
|
284
|
+
)
|
285
|
+
proxmox.logger = @logger
|
286
|
+
proxmox.logger_stderr = @logger_stderr
|
287
|
+
begin
|
288
|
+
yield proxmox
|
289
|
+
ensure
|
290
|
+
log_debug "[ #{@node}/#{@environment} ] - Proxmox API logs:\n#{proxmox_logs.string}"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# Maximum number of retries to perform on the Proxmox API.
|
296
|
+
NBR_RETRIES_MAX = 5
|
297
|
+
|
298
|
+
# Minimum seconds to wait between retries
|
299
|
+
RETRY_WAIT_TIME_SECS = 5
|
300
|
+
|
301
|
+
# Run a Proxmox task.
|
302
|
+
# Handle a retry mechanism in case of 5xx errors.
|
303
|
+
#
|
304
|
+
# Parameters::
|
305
|
+
# * *proxmox* (Proxmox): The Proxmox instance
|
306
|
+
# * *http_method* (Symbol): The HTTP method to call on the Proxmox instance
|
307
|
+
# * *pve_node* (String): Node on which the task is to be performed
|
308
|
+
# * *sub_path* (String): API sub-path to use (in the node API path)
|
309
|
+
# * *args* (Array): The list of additionnal arguments to give to the call
|
310
|
+
def run_proxmox_task(proxmox, http_method, pve_node, sub_path, *args)
|
311
|
+
task = nil
|
312
|
+
idx_try = 0
|
313
|
+
while task.nil? do
|
314
|
+
task = proxmox.send(http_method, "nodes/#{pve_node}/#{sub_path}", *args)
|
315
|
+
if task =~ /^NOK: error code = 5\d\d$/
|
316
|
+
log_warn "[ #{@node}/#{@environment} ] - Proxmox API call #{http_method} nodes/#{pve_node}/#{sub_path} #{args} returned error #{task} (attempt ##{idx_try}/#{NBR_RETRIES_MAX})"
|
317
|
+
task = nil
|
318
|
+
idx_try += 1
|
319
|
+
break if idx_try == NBR_RETRIES_MAX
|
320
|
+
sleep RETRY_WAIT_TIME_SECS + rand(5)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
if task.nil?
|
324
|
+
raise "[ #{@node}/#{@environment} ] - Proxmox API call #{http_method} nodes/#{pve_node}/#{sub_path} #{args} is constantly failing. Giving up."
|
325
|
+
else
|
326
|
+
wait_for_proxmox_task(proxmox, pve_node, task)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
# Wait for a given Proxmox task completion
|
331
|
+
#
|
332
|
+
# Parameters::
|
333
|
+
# * *proxmox* (Proxmox): The Proxmox instance
|
334
|
+
# * *pve_node* (String): Node on which the task is to be performed
|
335
|
+
# * *task* (String): The task ID
|
336
|
+
def wait_for_proxmox_task(proxmox, pve_node, task)
|
337
|
+
raise "Invalid task: #{task}" if task[0..3] == 'NOK:'
|
338
|
+
status = nil
|
339
|
+
loop do
|
340
|
+
status = task_status(proxmox, pve_node, task)
|
341
|
+
break unless status == 'running'
|
342
|
+
log_debug "[ #{@node}/#{@environment} ] - Wait for Proxmox task #{task} to complete..."
|
343
|
+
sleep 1
|
344
|
+
end
|
345
|
+
if status.split(':').last == 'OK'
|
346
|
+
log_debug "[ #{@node}/#{@environment} ] - Proxmox task #{task} completed."
|
347
|
+
else
|
348
|
+
raise "[ #{@node}/#{@environment} ] - Proxmox task #{task} completed with status #{status}"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# Get task status
|
353
|
+
#
|
354
|
+
# Parameters::
|
355
|
+
# * *proxmox* (Proxmox): The Proxmox instance
|
356
|
+
# * *pve_node* (String): Node on which the task status is to be queried
|
357
|
+
# * *task* (String): Task ID to query
|
358
|
+
# Result::
|
359
|
+
# * String: The task status
|
360
|
+
def task_status(proxmox, pve_node, task)
|
361
|
+
status_info = proxmox.get("nodes/#{pve_node}/tasks/#{task}/status")
|
362
|
+
"#{status_info['status']}#{status_info['exitstatus'] ? ":#{status_info['exitstatus']}" : ''}"
|
363
|
+
end
|
364
|
+
|
365
|
+
# Execute a command on the sync node and get back its JSON result
|
366
|
+
#
|
367
|
+
# Parameters::
|
368
|
+
# * *cmd* (String): The command to execute
|
369
|
+
# * *extra_files* (Hash<String,String>): Extra files (source file, destination directory) to include on the sync node [default: {}]
|
370
|
+
# Result::
|
371
|
+
# * Hash<Symbol,Object>: The result
|
372
|
+
def run_cmd_on_sync_node(cmd, extra_files: {})
|
373
|
+
# Create the ProxmoxWaiter config in a file to be uploaded
|
374
|
+
config_file = "#{Dir.tmpdir}/config_#{file_id}.json"
|
375
|
+
File.write(
|
376
|
+
config_file,
|
377
|
+
(proxmox_test_info[:test_config].merge(
|
378
|
+
proxmox_api_url: proxmox_test_info[:api_url],
|
379
|
+
futex_file: '/tmp/hpc_proxmox_allocations.futex',
|
380
|
+
logs_dir: '/tmp/hpc_proxmox_waiter_logs'
|
381
|
+
)).to_json
|
382
|
+
)
|
383
|
+
result = nil
|
384
|
+
begin
|
385
|
+
extra_files[config_file] = './proxmox/config'
|
386
|
+
cmd << " --config ./proxmox/config/#{File.basename(config_file)}"
|
387
|
+
stdout = nil
|
388
|
+
Credentials.with_credentials_for(:proxmox, @logger, @logger_stderr, url: proxmox_test_info[:api_url]) do |user, password|
|
389
|
+
# To avoid too fine concurrent accesses on the sync node file system, make sure all threads of our process wait for their turn to upload their files.
|
390
|
+
# Otherwise there is a small probability that a directory scp makes previously copied files inaccessible for a short period of time.
|
391
|
+
self.class.proxmox_waiter_files_mutex.synchronize do
|
392
|
+
@actions_executor.execute_actions(
|
393
|
+
{
|
394
|
+
proxmox_test_info[:sync_node] => [
|
395
|
+
{ scp: { "#{__dir__}/proxmox/" => '.' } },
|
396
|
+
{ remote_bash: extra_files.values.sort.uniq.map { |dir| "mkdir -p #{dir}" }.join("\n") }
|
397
|
+
] +
|
398
|
+
extra_files.map { |src_file, dst_dir| { scp: { src_file => dst_dir } } }
|
399
|
+
},
|
400
|
+
log_to_stdout: log_debug?
|
401
|
+
)
|
402
|
+
end
|
403
|
+
_exit_code, stdout, _stderr = @actions_executor.execute_actions(
|
404
|
+
{
|
405
|
+
proxmox_test_info[:sync_node] => {
|
406
|
+
remote_bash: {
|
407
|
+
commands: "#{@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : 'sudo -E '}./proxmox/#{cmd}",
|
408
|
+
env: {
|
409
|
+
'hpc_user_for_proxmox' => user,
|
410
|
+
'hpc_password_for_proxmox' => password,
|
411
|
+
'hpc_realm_for_proxmox' => ENV['hpc_realm_for_proxmox'] || 'pam'
|
412
|
+
}
|
413
|
+
}
|
414
|
+
}
|
415
|
+
},
|
416
|
+
log_to_stdout: log_debug?
|
417
|
+
)[proxmox_test_info[:sync_node]]
|
418
|
+
end
|
419
|
+
stdout_lines = stdout.split("\n")
|
420
|
+
result = JSON.parse(stdout_lines[stdout_lines.index('===== JSON =====') + 1..-1].join("\n")).transform_keys(&:to_sym)
|
421
|
+
raise "[ #{@node}/#{@environment} ] - Error returned by #{cmd}: #{result[:error]}" if result.key?(:error)
|
422
|
+
ensure
|
423
|
+
File.unlink(config_file)
|
424
|
+
end
|
425
|
+
result
|
426
|
+
end
|
427
|
+
|
428
|
+
# Query the Proxmox cluster to get authorization to create an LXC container that will use some resources.
|
429
|
+
# The returned VM ID/IP does not exist in the Proxmox cluster, and their usage is reserved for our node/environment.
|
430
|
+
#
|
431
|
+
# Parameters::
|
432
|
+
# * *vm_info* (Hash<symbol,Object>): The VM info we want to create
|
433
|
+
# Result::
|
434
|
+
# * Hash<Symbol, Object>: The details of the authorized container to be created:
|
435
|
+
# * *pve_node* (String): Name of the node on which the container is to be created
|
436
|
+
# * *vm_id* (Integer): Container ID to be used
|
437
|
+
# * *vm_ip* (String): IP address allocated for the LXC container to be created
|
438
|
+
def request_lxc_creation_for(vm_info)
|
439
|
+
log_debug "[ #{@node}/#{@environment} ] - Request LXC creation for #{vm_info}..."
|
440
|
+
# Create a unique file name
|
441
|
+
create_config_file = "#{Dir.tmpdir}/create_#{file_id}.json"
|
442
|
+
File.write(create_config_file, vm_info.to_json)
|
443
|
+
created_vm_info = nil
|
444
|
+
begin
|
445
|
+
created_vm_info = run_cmd_on_sync_node(
|
446
|
+
"reserve_proxmox_container --create ./proxmox/create/#{File.basename(create_config_file)}",
|
447
|
+
extra_files: { create_config_file => './proxmox/create' }
|
448
|
+
)
|
449
|
+
ensure
|
450
|
+
File.unlink(create_config_file)
|
451
|
+
end
|
452
|
+
created_vm_info
|
453
|
+
end
|
454
|
+
|
455
|
+
# Contact the sync node to notify a container release
|
456
|
+
#
|
457
|
+
# Parameters::
|
458
|
+
# * *vm_id* (Integer): The VM ID to be released
|
459
|
+
# Result::
|
460
|
+
# * Hash<Symbol, Object>: The details of the released container:
|
461
|
+
# * *pve_node* (String): Name of the node on which the container was reserved (if found)
|
462
|
+
def release_lxc_container(vm_id)
|
463
|
+
log_debug "[ #{@node}/#{@environment} ] - Release LXC VM #{vm_id}..."
|
464
|
+
# Create a unique file name
|
465
|
+
destroy_config_file = "#{Dir.tmpdir}/destroy_#{file_id}.json"
|
466
|
+
File.write(destroy_config_file, {
|
467
|
+
vm_id: vm_id,
|
468
|
+
node: @node,
|
469
|
+
environment: @environment
|
470
|
+
}.to_json)
|
471
|
+
destroyed_vm_info = nil
|
472
|
+
begin
|
473
|
+
destroyed_vm_info = run_cmd_on_sync_node(
|
474
|
+
"reserve_proxmox_container --destroy ./proxmox/destroy/#{File.basename(destroy_config_file)}",
|
475
|
+
extra_files: { destroy_config_file => './proxmox/destroy' }
|
476
|
+
)
|
477
|
+
ensure
|
478
|
+
File.unlink(destroy_config_file)
|
479
|
+
end
|
480
|
+
destroyed_vm_info
|
481
|
+
end
|
482
|
+
|
483
|
+
# Maximum size a file ID can have (file IDs are used differentiate create/destroy/config files for a given node/environment).
|
484
|
+
# File names are 255 chars max.
|
485
|
+
# Consider that it is to be used on the following patterns: (config|create|destroy)_<ID>.json
|
486
|
+
# So remaining length is 255 - 13 = 242 characters.
|
487
|
+
MAX_FILE_ID_SIZE = 242
|
488
|
+
|
489
|
+
# Get an ID unique for theis node/environment and that can be used in file names.
|
490
|
+
#
|
491
|
+
# Result::
|
492
|
+
# * String: ID
|
493
|
+
def file_id
|
494
|
+
# If the file name exceeds the maximum length, then generate an MD5 to truncate the end of the file name.
|
495
|
+
result = "#{@node}_#{@environment}"
|
496
|
+
if result.size > MAX_FILE_ID_SIZE
|
497
|
+
# Truncate it, but add a unique ID in it.
|
498
|
+
result = "-#{Digest::MD5.hexdigest(result)[0..7]}"
|
499
|
+
result = "#{@node}_#{@environment}"[0..MAX_FILE_ID_SIZE - result.size - 1] + result
|
500
|
+
end
|
501
|
+
result
|
502
|
+
end
|
503
|
+
|
504
|
+
# Get details about the proxmox instance to be used
|
505
|
+
#
|
506
|
+
# Result::
|
507
|
+
# * Hash<Symbol,Object>: Configuration of the Proxmox instance to be used:
|
508
|
+
# * *api_url* (String): The Proxmox API URL
|
509
|
+
# * *sync_node* (String): Node to be used to synchronize Proxmox resources acquisition
|
510
|
+
# * *test_config* (Hash<Symbol,Object>): The test configuration. Check ProxmoxWaiter#initialize (config_file structure) method to get details.
|
511
|
+
# * *vm_config* (Hash<Symbol,Object>): Extra configuration of a created container. Check #request_lxc_creation_for results to get details.
|
512
|
+
# * *default_timeout* (Integer): The default timeout tobe applied when starting/stopping containers [default: 3600].
|
513
|
+
def proxmox_test_info
|
514
|
+
@config.proxmox_servers.first
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
end
|
519
|
+
|
520
|
+
end
|
521
|
+
|
522
|
+
end
|