mtncloud-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.dockerignore +20 -0
- data/.github/pull_request_template.md +14 -0
- data/.github/workflows/ci.yml +56 -0
- data/.github/workflows/release.yml +46 -0
- data/.gitignore +25 -0
- data/CLAUDE.md +24 -0
- data/CONTRIBUTING.md +91 -0
- data/Dockerfile +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +187 -0
- data/Rakefile +26 -0
- data/bin/mcs +3 -0
- data/bin/mtncloud +27 -0
- data/lib/mtncloud/api/account_groups_interface.rb +48 -0
- data/lib/mtncloud/api/account_users_interface.rb +68 -0
- data/lib/mtncloud/api/accounts_interface.rb +9 -0
- data/lib/mtncloud/api/activity_interface.rb +9 -0
- data/lib/mtncloud/api/affinity_groups_interface.rb +46 -0
- data/lib/mtncloud/api/api_client.rb +1091 -0
- data/lib/mtncloud/api/appliance_settings_interface.rb +49 -0
- data/lib/mtncloud/api/approvals_interface.rb +32 -0
- data/lib/mtncloud/api/apps_interface.rb +180 -0
- data/lib/mtncloud/api/archive_buckets_interface.rb +116 -0
- data/lib/mtncloud/api/archive_files_interface.rb +173 -0
- data/lib/mtncloud/api/audit_interface.rb +9 -0
- data/lib/mtncloud/api/auth_interface.rb +58 -0
- data/lib/mtncloud/api/backup_jobs_interface.rb +13 -0
- data/lib/mtncloud/api/backup_restores_interface.rb +27 -0
- data/lib/mtncloud/api/backup_results_interface.rb +32 -0
- data/lib/mtncloud/api/backup_service_types_interface.rb +9 -0
- data/lib/mtncloud/api/backup_services_interface.rb +9 -0
- data/lib/mtncloud/api/backup_settings_interface.rb +20 -0
- data/lib/mtncloud/api/backup_types_interface.rb +9 -0
- data/lib/mtncloud/api/backups_interface.rb +21 -0
- data/lib/mtncloud/api/billing_interface.rb +34 -0
- data/lib/mtncloud/api/blueprints_interface.rb +70 -0
- data/lib/mtncloud/api/body_io.rb +22 -0
- data/lib/mtncloud/api/budgets_interface.rb +48 -0
- data/lib/mtncloud/api/catalog_item_types_interface.rb +29 -0
- data/lib/mtncloud/api/certificate_types_interface.rb +14 -0
- data/lib/mtncloud/api/certificates_interface.rb +9 -0
- data/lib/mtncloud/api/clients_interface.rb +41 -0
- data/lib/mtncloud/api/cloud_datastores_interface.rb +48 -0
- data/lib/mtncloud/api/cloud_folders_interface.rb +41 -0
- data/lib/mtncloud/api/cloud_policies_interface.rb +41 -0
- data/lib/mtncloud/api/cloud_resource_pools_interface.rb +66 -0
- data/lib/mtncloud/api/clouds_interface.rb +217 -0
- data/lib/mtncloud/api/clusters_interface.rb +471 -0
- data/lib/mtncloud/api/containers_interface.rb +145 -0
- data/lib/mtncloud/api/credential_types_interface.rb +9 -0
- data/lib/mtncloud/api/credentials_interface.rb +9 -0
- data/lib/mtncloud/api/custom_instance_types_interface.rb +99 -0
- data/lib/mtncloud/api/cypher_interface.rb +51 -0
- data/lib/mtncloud/api/dashboard_interface.rb +14 -0
- data/lib/mtncloud/api/datastores_interface.rb +21 -0
- data/lib/mtncloud/api/deploy_interface.rb +44 -0
- data/lib/mtncloud/api/deployments_interface.rb +79 -0
- data/lib/mtncloud/api/distributed_workers_interface.rb +41 -0
- data/lib/mtncloud/api/email_templates_interface.rb +53 -0
- data/lib/mtncloud/api/environments_interface.rb +48 -0
- data/lib/mtncloud/api/execute_schedules_interface.rb +71 -0
- data/lib/mtncloud/api/execution_request_interface.rb +27 -0
- data/lib/mtncloud/api/file_copy_request_interface.rb +68 -0
- data/lib/mtncloud/api/forgot_password_interface.rb +17 -0
- data/lib/mtncloud/api/group_policies_interface.rb +41 -0
- data/lib/mtncloud/api/groups_interface.rb +73 -0
- data/lib/mtncloud/api/guidance_interface.rb +44 -0
- data/lib/mtncloud/api/guidance_settings_interface.rb +17 -0
- data/lib/mtncloud/api/health_interface.rb +100 -0
- data/lib/mtncloud/api/host_vm_groups_interface.rb +37 -0
- data/lib/mtncloud/api/hub_interface.rb +25 -0
- data/lib/mtncloud/api/image_builder_boot_scripts_interface.rb +41 -0
- data/lib/mtncloud/api/image_builder_image_builds_interface.rb +73 -0
- data/lib/mtncloud/api/image_builder_interface.rb +20 -0
- data/lib/mtncloud/api/image_builder_preseed_scripts_interface.rb +41 -0
- data/lib/mtncloud/api/instance_types_interface.rb +20 -0
- data/lib/mtncloud/api/instances_interface.rb +453 -0
- data/lib/mtncloud/api/integration_types_interface.rb +14 -0
- data/lib/mtncloud/api/integrations_interface.rb +74 -0
- data/lib/mtncloud/api/invoice_line_items_interface.rb +9 -0
- data/lib/mtncloud/api/invoices_interface.rb +28 -0
- data/lib/mtncloud/api/jobs_interface.rb +83 -0
- data/lib/mtncloud/api/key_pairs_interface.rb +57 -0
- data/lib/mtncloud/api/library_cluster_layouts_interface.rb +47 -0
- data/lib/mtncloud/api/library_cluster_packages_interface.rb +60 -0
- data/lib/mtncloud/api/library_container_scripts_interface.rb +43 -0
- data/lib/mtncloud/api/library_container_templates_interface.rb +43 -0
- data/lib/mtncloud/api/library_container_types_interface.rb +59 -0
- data/lib/mtncloud/api/library_container_upgrades_interface.rb +60 -0
- data/lib/mtncloud/api/library_instance_types_interface.rb +74 -0
- data/lib/mtncloud/api/library_layouts_interface.rb +69 -0
- data/lib/mtncloud/api/library_operating_systems_interface.rb +63 -0
- data/lib/mtncloud/api/library_spec_template_types_interface.rb +43 -0
- data/lib/mtncloud/api/library_spec_templates_interface.rb +43 -0
- data/lib/mtncloud/api/license_interface.rb +30 -0
- data/lib/mtncloud/api/load_balancer_monitors_interface.rb +9 -0
- data/lib/mtncloud/api/load_balancer_pool_nodes_interface.rb +8 -0
- data/lib/mtncloud/api/load_balancer_pools_interface.rb +9 -0
- data/lib/mtncloud/api/load_balancer_pools_secondary_interface.rb +9 -0
- data/lib/mtncloud/api/load_balancer_profiles_interface.rb +9 -0
- data/lib/mtncloud/api/load_balancer_types_interface.rb +9 -0
- data/lib/mtncloud/api/load_balancer_virtual_servers_interface.rb +18 -0
- data/lib/mtncloud/api/load_balancers_interface.rb +14 -0
- data/lib/mtncloud/api/log_settings_interface.rb +44 -0
- data/lib/mtncloud/api/logs_interface.rb +37 -0
- data/lib/mtncloud/api/migrations_interface.rb +49 -0
- data/lib/mtncloud/api/monitoring_alerts_interface.rb +39 -0
- data/lib/mtncloud/api/monitoring_apps_interface.rb +69 -0
- data/lib/mtncloud/api/monitoring_checks_interface.rb +103 -0
- data/lib/mtncloud/api/monitoring_contacts_interface.rb +41 -0
- data/lib/mtncloud/api/monitoring_groups_interface.rb +77 -0
- data/lib/mtncloud/api/monitoring_incidents_interface.rb +107 -0
- data/lib/mtncloud/api/monitoring_interface.rb +35 -0
- data/lib/mtncloud/api/monitoring_settings_interface.rb +21 -0
- data/lib/mtncloud/api/network_dhcp_relays_interface.rb +36 -0
- data/lib/mtncloud/api/network_dhcp_servers_interface.rb +36 -0
- data/lib/mtncloud/api/network_domain_records_interface.rb +41 -0
- data/lib/mtncloud/api/network_domains_interface.rb +41 -0
- data/lib/mtncloud/api/network_edge_clusters_interface.rb +26 -0
- data/lib/mtncloud/api/network_floating_ips_interface.rb +40 -0
- data/lib/mtncloud/api/network_groups_interface.rb +41 -0
- data/lib/mtncloud/api/network_pool_ips_interface.rb +41 -0
- data/lib/mtncloud/api/network_pool_server_types_interface.rb +9 -0
- data/lib/mtncloud/api/network_pool_servers_interface.rb +48 -0
- data/lib/mtncloud/api/network_pools_interface.rb +41 -0
- data/lib/mtncloud/api/network_proxies_interface.rb +41 -0
- data/lib/mtncloud/api/network_routers_interface.rb +181 -0
- data/lib/mtncloud/api/network_security_server_types_interface.rb +9 -0
- data/lib/mtncloud/api/network_security_servers_interface.rb +27 -0
- data/lib/mtncloud/api/network_server_groups_interface.rb +7 -0
- data/lib/mtncloud/api/network_server_types_interface.rb +9 -0
- data/lib/mtncloud/api/network_servers_interface.rb +102 -0
- data/lib/mtncloud/api/network_services_interface.rb +63 -0
- data/lib/mtncloud/api/network_static_routes_interface.rb +36 -0
- data/lib/mtncloud/api/network_subnets_interface.rb +42 -0
- data/lib/mtncloud/api/network_types_interface.rb +20 -0
- data/lib/mtncloud/api/networks_interface.rb +48 -0
- data/lib/mtncloud/api/option_type_forms_interface.rb +9 -0
- data/lib/mtncloud/api/option_type_lists_interface.rb +53 -0
- data/lib/mtncloud/api/option_types_interface.rb +41 -0
- data/lib/mtncloud/api/options_interface.rb +17 -0
- data/lib/mtncloud/api/packages_interface.rb +112 -0
- data/lib/mtncloud/api/ping_interface.rb +22 -0
- data/lib/mtncloud/api/plugins_interface.rb +22 -0
- data/lib/mtncloud/api/policies_interface.rb +56 -0
- data/lib/mtncloud/api/power_schedules_interface.rb +71 -0
- data/lib/mtncloud/api/price_sets_interface.rb +39 -0
- data/lib/mtncloud/api/prices_interface.rb +71 -0
- data/lib/mtncloud/api/processes_interface.rb +40 -0
- data/lib/mtncloud/api/projects_interface.rb +33 -0
- data/lib/mtncloud/api/provision_types_interface.rb +24 -0
- data/lib/mtncloud/api/provisioning_license_types_interface.rb +31 -0
- data/lib/mtncloud/api/provisioning_licenses_interface.rb +60 -0
- data/lib/mtncloud/api/provisioning_settings_interface.rb +26 -0
- data/lib/mtncloud/api/read_interface.rb +24 -0
- data/lib/mtncloud/api/reports_interface.rb +70 -0
- data/lib/mtncloud/api/resource_pool_groups_interface.rb +51 -0
- data/lib/mtncloud/api/rest_interface.rb +37 -0
- data/lib/mtncloud/api/roles_interface.rb +151 -0
- data/lib/mtncloud/api/scale_thresholds_interface.rb +9 -0
- data/lib/mtncloud/api/search_interface.rb +13 -0
- data/lib/mtncloud/api/secondary_read_interface.rb +25 -0
- data/lib/mtncloud/api/secondary_rest_interface.rb +42 -0
- data/lib/mtncloud/api/security_group_rules_interface.rb +35 -0
- data/lib/mtncloud/api/security_groups_interface.rb +56 -0
- data/lib/mtncloud/api/security_package_types_interface.rb +9 -0
- data/lib/mtncloud/api/security_packages_interface.rb +9 -0
- data/lib/mtncloud/api/security_scans_interface.rb +9 -0
- data/lib/mtncloud/api/server_devices_interface.rb +30 -0
- data/lib/mtncloud/api/server_types_interface.rb +20 -0
- data/lib/mtncloud/api/servers_interface.rb +230 -0
- data/lib/mtncloud/api/service_catalog_interface.rb +89 -0
- data/lib/mtncloud/api/service_plans_interface.rb +62 -0
- data/lib/mtncloud/api/setup_interface.rb +46 -0
- data/lib/mtncloud/api/snapshots_interface.rb +19 -0
- data/lib/mtncloud/api/storage_datastores_interface.rb +44 -0
- data/lib/mtncloud/api/storage_providers_interface.rb +151 -0
- data/lib/mtncloud/api/storage_server_types_interface.rb +14 -0
- data/lib/mtncloud/api/storage_servers_interface.rb +9 -0
- data/lib/mtncloud/api/storage_volume_types_interface.rb +9 -0
- data/lib/mtncloud/api/storage_volumes_interface.rb +24 -0
- data/lib/mtncloud/api/subnet_types_interface.rb +20 -0
- data/lib/mtncloud/api/subnets_interface.rb +41 -0
- data/lib/mtncloud/api/support_bundles_interface.rb +46 -0
- data/lib/mtncloud/api/system_types_interface.rb +13 -0
- data/lib/mtncloud/api/systems_interface.rb +55 -0
- data/lib/mtncloud/api/task_sets_interface.rb +52 -0
- data/lib/mtncloud/api/tasks_interface.rb +66 -0
- data/lib/mtncloud/api/tokens_interface.rb +39 -0
- data/lib/mtncloud/api/usage_interface.rb +18 -0
- data/lib/mtncloud/api/user_groups_interface.rb +59 -0
- data/lib/mtncloud/api/user_settings_interface.rb +90 -0
- data/lib/mtncloud/api/user_sources_interface.rb +99 -0
- data/lib/mtncloud/api/users_interface.rb +33 -0
- data/lib/mtncloud/api/vdi_allocations_interface.rb +9 -0
- data/lib/mtncloud/api/vdi_apps_interface.rb +9 -0
- data/lib/mtncloud/api/vdi_gateways_interface.rb +9 -0
- data/lib/mtncloud/api/vdi_interface.rb +28 -0
- data/lib/mtncloud/api/vdi_pools_interface.rb +19 -0
- data/lib/mtncloud/api/virtual_images_interface.rb +210 -0
- data/lib/mtncloud/api/virtual_servers_interface.rb +9 -0
- data/lib/mtncloud/api/virtual_switches_interface.rb +9 -0
- data/lib/mtncloud/api/whitelabel_settings_interface.rb +57 -0
- data/lib/mtncloud/api/whoami_interface.rb +13 -0
- data/lib/mtncloud/api/wiki_interface.rb +48 -0
- data/lib/mtncloud/api.rb +12 -0
- data/lib/mtncloud/benchmarking.rb +259 -0
- data/lib/mtncloud/cli/cli_command.rb +2281 -0
- data/lib/mtncloud/cli/cli_registry.rb +337 -0
- data/lib/mtncloud/cli/commands/access_token_command.rb +201 -0
- data/lib/mtncloud/cli/commands/account_groups_command.rb +530 -0
- data/lib/mtncloud/cli/commands/activity_command.rb +149 -0
- data/lib/mtncloud/cli/commands/affinity_groups_command.rb +554 -0
- data/lib/mtncloud/cli/commands/alias_command.rb +278 -0
- data/lib/mtncloud/cli/commands/appliance_settings_command.rb +382 -0
- data/lib/mtncloud/cli/commands/approvals_command.rb +236 -0
- data/lib/mtncloud/cli/commands/apps.rb +2549 -0
- data/lib/mtncloud/cli/commands/archives_command.rb +2161 -0
- data/lib/mtncloud/cli/commands/audit.rb +188 -0
- data/lib/mtncloud/cli/commands/backup_jobs_command.rb +366 -0
- data/lib/mtncloud/cli/commands/backup_restores_command.rb +144 -0
- data/lib/mtncloud/cli/commands/backup_results_command.rb +149 -0
- data/lib/mtncloud/cli/commands/backup_services_command.rb +44 -0
- data/lib/mtncloud/cli/commands/backup_settings_command.rb +184 -0
- data/lib/mtncloud/cli/commands/backup_types_command.rb +53 -0
- data/lib/mtncloud/cli/commands/backups_command.rb +674 -0
- data/lib/mtncloud/cli/commands/benchmark_command.rb +458 -0
- data/lib/mtncloud/cli/commands/blueprints_command.rb +2297 -0
- data/lib/mtncloud/cli/commands/boot_scripts_command.rb +379 -0
- data/lib/mtncloud/cli/commands/budgets_command.rb +754 -0
- data/lib/mtncloud/cli/commands/cat_command.rb +45 -0
- data/lib/mtncloud/cli/commands/catalog_item_types_command.rb +858 -0
- data/lib/mtncloud/cli/commands/certificates_command.rb +575 -0
- data/lib/mtncloud/cli/commands/change_password_command.rb +132 -0
- data/lib/mtncloud/cli/commands/clients_command.rb +331 -0
- data/lib/mtncloud/cli/commands/cloud_datastores_command.rb +543 -0
- data/lib/mtncloud/cli/commands/cloud_folders_command.rb +512 -0
- data/lib/mtncloud/cli/commands/cloud_resource_pools_command.rb +870 -0
- data/lib/mtncloud/cli/commands/clouds.rb +2037 -0
- data/lib/mtncloud/cli/commands/clouds_types.rb +140 -0
- data/lib/mtncloud/cli/commands/cluster_types.rb +179 -0
- data/lib/mtncloud/cli/commands/clusters.rb +5855 -0
- data/lib/mtncloud/cli/commands/coloring_command.rb +82 -0
- data/lib/mtncloud/cli/commands/containers_command.rb +967 -0
- data/lib/mtncloud/cli/commands/credential_types_command.rb +36 -0
- data/lib/mtncloud/cli/commands/credentials_command.rb +124 -0
- data/lib/mtncloud/cli/commands/curl_command.rb +168 -0
- data/lib/mtncloud/cli/commands/cypher_command.rb +587 -0
- data/lib/mtncloud/cli/commands/dashboard_command.rb +300 -0
- data/lib/mtncloud/cli/commands/debug_command.rb +75 -0
- data/lib/mtncloud/cli/commands/deploy.rb +485 -0
- data/lib/mtncloud/cli/commands/deployments.rb +923 -0
- data/lib/mtncloud/cli/commands/deploys.rb +485 -0
- data/lib/mtncloud/cli/commands/distributed_workers_command.rb +282 -0
- data/lib/mtncloud/cli/commands/echo_command.rb +61 -0
- data/lib/mtncloud/cli/commands/edit_profile_command.rb +57 -0
- data/lib/mtncloud/cli/commands/edit_rc_command.rb +77 -0
- data/lib/mtncloud/cli/commands/email_templates_command.rb +373 -0
- data/lib/mtncloud/cli/commands/environments_command.rb +401 -0
- data/lib/mtncloud/cli/commands/execute_schedules_command.rb +735 -0
- data/lib/mtncloud/cli/commands/execution_request_command.rb +333 -0
- data/lib/mtncloud/cli/commands/exit_command.rb +34 -0
- data/lib/mtncloud/cli/commands/file_copy_request_command.rb +352 -0
- data/lib/mtncloud/cli/commands/forgot_password.rb +133 -0
- data/lib/mtncloud/cli/commands/get_prompt_command.rb +36 -0
- data/lib/mtncloud/cli/commands/groups.rb +818 -0
- data/lib/mtncloud/cli/commands/guidance_command.rb +529 -0
- data/lib/mtncloud/cli/commands/guidance_settings.rb +148 -0
- data/lib/mtncloud/cli/commands/health_command.rb +1046 -0
- data/lib/mtncloud/cli/commands/history_command.rb +60 -0
- data/lib/mtncloud/cli/commands/host_vm_groups_command.rb +423 -0
- data/lib/mtncloud/cli/commands/hosts.rb +2986 -0
- data/lib/mtncloud/cli/commands/hub.rb +215 -0
- data/lib/mtncloud/cli/commands/image_builder_command.rb +1197 -0
- data/lib/mtncloud/cli/commands/instance_types.rb +163 -0
- data/lib/mtncloud/cli/commands/instances.rb +5813 -0
- data/lib/mtncloud/cli/commands/integrations_command.rb +1412 -0
- data/lib/mtncloud/cli/commands/invoices_command.rb +1151 -0
- data/lib/mtncloud/cli/commands/jobs_command.rb +998 -0
- data/lib/mtncloud/cli/commands/key_pairs.rb +470 -0
- data/lib/mtncloud/cli/commands/library_cluster_layouts_command.rb +901 -0
- data/lib/mtncloud/cli/commands/library_cluster_packages_command.rb +552 -0
- data/lib/mtncloud/cli/commands/library_container_scripts_command.rb +446 -0
- data/lib/mtncloud/cli/commands/library_container_templates_command.rb +526 -0
- data/lib/mtncloud/cli/commands/library_container_types_command.rb +698 -0
- data/lib/mtncloud/cli/commands/library_forms_command.rb +625 -0
- data/lib/mtncloud/cli/commands/library_instance_types_command.rb +668 -0
- data/lib/mtncloud/cli/commands/library_layouts_command.rb +849 -0
- data/lib/mtncloud/cli/commands/library_operating_systems_command.rb +671 -0
- data/lib/mtncloud/cli/commands/library_option_lists_command.rb +503 -0
- data/lib/mtncloud/cli/commands/library_option_types_command.rb +329 -0
- data/lib/mtncloud/cli/commands/library_spec_templates_command.rb +547 -0
- data/lib/mtncloud/cli/commands/library_upgrades_command.rb +596 -0
- data/lib/mtncloud/cli/commands/license.rb +475 -0
- data/lib/mtncloud/cli/commands/load_balancer_monitors.rb +70 -0
- data/lib/mtncloud/cli/commands/load_balancer_pool_nodes.rb +87 -0
- data/lib/mtncloud/cli/commands/load_balancer_pools.rb +129 -0
- data/lib/mtncloud/cli/commands/load_balancer_profiles.rb +64 -0
- data/lib/mtncloud/cli/commands/load_balancer_types.rb +38 -0
- data/lib/mtncloud/cli/commands/load_balancer_virtual_servers.rb +147 -0
- data/lib/mtncloud/cli/commands/load_balancers.rb +189 -0
- data/lib/mtncloud/cli/commands/log_level_command.rb +54 -0
- data/lib/mtncloud/cli/commands/log_settings_command.rb +443 -0
- data/lib/mtncloud/cli/commands/login.rb +148 -0
- data/lib/mtncloud/cli/commands/logout.rb +63 -0
- data/lib/mtncloud/cli/commands/logs_command.rb +140 -0
- data/lib/mtncloud/cli/commands/man_command.rb +409 -0
- data/lib/mtncloud/cli/commands/migrations.rb +453 -0
- data/lib/mtncloud/cli/commands/monitoring_alerts_command.rb +791 -0
- data/lib/mtncloud/cli/commands/monitoring_apps_command.rb +716 -0
- data/lib/mtncloud/cli/commands/monitoring_checks_command.rb +766 -0
- data/lib/mtncloud/cli/commands/monitoring_contacts_command.rb +339 -0
- data/lib/mtncloud/cli/commands/monitoring_groups_command.rb +674 -0
- data/lib/mtncloud/cli/commands/monitoring_incidents_command.rb +835 -0
- data/lib/mtncloud/cli/commands/monitoring_settings.rb +212 -0
- data/lib/mtncloud/cli/commands/network_dhcp_relays_command.rb +375 -0
- data/lib/mtncloud/cli/commands/network_dhcp_servers_command.rb +366 -0
- data/lib/mtncloud/cli/commands/network_domains_command.rb +896 -0
- data/lib/mtncloud/cli/commands/network_edge_clusters_command.rb +288 -0
- data/lib/mtncloud/cli/commands/network_firewalls_command.rb +783 -0
- data/lib/mtncloud/cli/commands/network_floating_ips.rb +147 -0
- data/lib/mtncloud/cli/commands/network_groups_command.rb +654 -0
- data/lib/mtncloud/cli/commands/network_pool_server_types.rb +20 -0
- data/lib/mtncloud/cli/commands/network_pool_servers_command.rb +318 -0
- data/lib/mtncloud/cli/commands/network_pools_command.rb +903 -0
- data/lib/mtncloud/cli/commands/network_proxies_command.rb +578 -0
- data/lib/mtncloud/cli/commands/network_routers_command.rb +2628 -0
- data/lib/mtncloud/cli/commands/network_security_server_types.rb +20 -0
- data/lib/mtncloud/cli/commands/network_server_groups_command.rb +222 -0
- data/lib/mtncloud/cli/commands/network_server_types_command.rb +20 -0
- data/lib/mtncloud/cli/commands/network_servers_command.rb +398 -0
- data/lib/mtncloud/cli/commands/network_services_command.rb +198 -0
- data/lib/mtncloud/cli/commands/network_static_routes_command.rb +451 -0
- data/lib/mtncloud/cli/commands/network_transport_zones_command.rb +412 -0
- data/lib/mtncloud/cli/commands/networks_command.rb +1692 -0
- data/lib/mtncloud/cli/commands/open_command.rb +30 -0
- data/lib/mtncloud/cli/commands/options.rb +231 -0
- data/lib/mtncloud/cli/commands/packages_command.rb +822 -0
- data/lib/mtncloud/cli/commands/ping.rb +242 -0
- data/lib/mtncloud/cli/commands/plugins.rb +214 -0
- data/lib/mtncloud/cli/commands/policies_command.rb +990 -0
- data/lib/mtncloud/cli/commands/power_schedules_command.rb +731 -0
- data/lib/mtncloud/cli/commands/preseed_scripts_command.rb +378 -0
- data/lib/mtncloud/cli/commands/price_sets_command.rb +557 -0
- data/lib/mtncloud/cli/commands/prices_command.rb +692 -0
- data/lib/mtncloud/cli/commands/processes_command.rb +469 -0
- data/lib/mtncloud/cli/commands/projects_command.rb +537 -0
- data/lib/mtncloud/cli/commands/provisioning_licenses_command.rb +509 -0
- data/lib/mtncloud/cli/commands/provisioning_settings_command.rb +238 -0
- data/lib/mtncloud/cli/commands/recent_activity_command.rb +171 -0
- data/lib/mtncloud/cli/commands/remote.rb +1818 -0
- data/lib/mtncloud/cli/commands/reports_command.rb +724 -0
- data/lib/mtncloud/cli/commands/resource_pool_groups_command.rb +586 -0
- data/lib/mtncloud/cli/commands/rm_command.rb +14 -0
- data/lib/mtncloud/cli/commands/roles.rb +3120 -0
- data/lib/mtncloud/cli/commands/scale_thresholds.rb +103 -0
- data/lib/mtncloud/cli/commands/search_command.rb +184 -0
- data/lib/mtncloud/cli/commands/security_group_rules.rb +230 -0
- data/lib/mtncloud/cli/commands/security_groups.rb +1294 -0
- data/lib/mtncloud/cli/commands/security_package_types.rb +32 -0
- data/lib/mtncloud/cli/commands/security_packages.rb +84 -0
- data/lib/mtncloud/cli/commands/security_scans.rb +107 -0
- data/lib/mtncloud/cli/commands/self_service_command.rb +17 -0
- data/lib/mtncloud/cli/commands/server_devices_command.rb +207 -0
- data/lib/mtncloud/cli/commands/service_catalog_command.rb +1528 -0
- data/lib/mtncloud/cli/commands/service_plans_command.rb +895 -0
- data/lib/mtncloud/cli/commands/set_prompt_command.rb +51 -0
- data/lib/mtncloud/cli/commands/setup.rb +423 -0
- data/lib/mtncloud/cli/commands/shell.rb +717 -0
- data/lib/mtncloud/cli/commands/sleep_command.rb +43 -0
- data/lib/mtncloud/cli/commands/snapshots.rb +156 -0
- data/lib/mtncloud/cli/commands/source_command.rb +30 -0
- data/lib/mtncloud/cli/commands/ssl_verification_command.rb +47 -0
- data/lib/mtncloud/cli/commands/storage_datastores.rb +457 -0
- data/lib/mtncloud/cli/commands/storage_providers_command.rb +1401 -0
- data/lib/mtncloud/cli/commands/storage_server_types.rb +45 -0
- data/lib/mtncloud/cli/commands/storage_servers.rb +116 -0
- data/lib/mtncloud/cli/commands/storage_volume_types.rb +45 -0
- data/lib/mtncloud/cli/commands/storage_volumes.rb +236 -0
- data/lib/mtncloud/cli/commands/subnets_command.rb +819 -0
- data/lib/mtncloud/cli/commands/support_bundles_command.rb +606 -0
- data/lib/mtncloud/cli/commands/systems.rb +1203 -0
- data/lib/mtncloud/cli/commands/tasks.rb +1391 -0
- data/lib/mtncloud/cli/commands/tee_command.rb +14 -0
- data/lib/mtncloud/cli/commands/tenants_command.rb +315 -0
- data/lib/mtncloud/cli/commands/tokens_command.rb +391 -0
- data/lib/mtncloud/cli/commands/update_command.rb +46 -0
- data/lib/mtncloud/cli/commands/usage_command.rb +203 -0
- data/lib/mtncloud/cli/commands/user_groups_command.rb +512 -0
- data/lib/mtncloud/cli/commands/user_settings_command.rb +849 -0
- data/lib/mtncloud/cli/commands/user_sources_command.rb +1065 -0
- data/lib/mtncloud/cli/commands/users.rb +897 -0
- data/lib/mtncloud/cli/commands/vdi_allocations_command.rb +159 -0
- data/lib/mtncloud/cli/commands/vdi_apps_command.rb +317 -0
- data/lib/mtncloud/cli/commands/vdi_command.rb +359 -0
- data/lib/mtncloud/cli/commands/vdi_gateways_command.rb +290 -0
- data/lib/mtncloud/cli/commands/vdi_pools_command.rb +574 -0
- data/lib/mtncloud/cli/commands/version_command.rb +38 -0
- data/lib/mtncloud/cli/commands/view.rb +107 -0
- data/lib/mtncloud/cli/commands/virtual_images.rb +1362 -0
- data/lib/mtncloud/cli/commands/virtual_switches_command.rb +336 -0
- data/lib/mtncloud/cli/commands/whitelabel_settings_command.rb +653 -0
- data/lib/mtncloud/cli/commands/whoami.rb +323 -0
- data/lib/mtncloud/cli/commands/wiki_command.rb +448 -0
- data/lib/mtncloud/cli/commands/workflows.rb +1022 -0
- data/lib/mtncloud/cli/credentials.rb +482 -0
- data/lib/mtncloud/cli/dot_file.rb +180 -0
- data/lib/mtncloud/cli/error_handler.rb +307 -0
- data/lib/mtncloud/cli/errors.rb +53 -0
- data/lib/mtncloud/cli/expression_parser.rb +153 -0
- data/lib/mtncloud/cli/mixins/accounts_helper.rb +484 -0
- data/lib/mtncloud/cli/mixins/affinity_helper.rb +118 -0
- data/lib/mtncloud/cli/mixins/backups_helper.rb +200 -0
- data/lib/mtncloud/cli/mixins/deployments_helper.rb +163 -0
- data/lib/mtncloud/cli/mixins/execution_request_helper.rb +50 -0
- data/lib/mtncloud/cli/mixins/infrastructure_helper.rb +966 -0
- data/lib/mtncloud/cli/mixins/jobs_helper.rb +202 -0
- data/lib/mtncloud/cli/mixins/library_helper.rb +539 -0
- data/lib/mtncloud/cli/mixins/load_balancers_helper.rb +176 -0
- data/lib/mtncloud/cli/mixins/logs_helper.rb +131 -0
- data/lib/mtncloud/cli/mixins/monitoring_helper.rb +876 -0
- data/lib/mtncloud/cli/mixins/networks_helper.rb +62 -0
- data/lib/mtncloud/cli/mixins/operations_helper.rb +41 -0
- data/lib/mtncloud/cli/mixins/option_source_helper.rb +254 -0
- data/lib/mtncloud/cli/mixins/print_helper.rb +1631 -0
- data/lib/mtncloud/cli/mixins/processes_helper.rb +286 -0
- data/lib/mtncloud/cli/mixins/prompt_helper.rb +136 -0
- data/lib/mtncloud/cli/mixins/provisioning_helper.rb +2963 -0
- data/lib/mtncloud/cli/mixins/remote_helper.rb +139 -0
- data/lib/mtncloud/cli/mixins/rest_command.rb +994 -0
- data/lib/mtncloud/cli/mixins/secondary_rest_command.rb +700 -0
- data/lib/mtncloud/cli/mixins/storage_servers_helper.rb +93 -0
- data/lib/mtncloud/cli/mixins/storage_volumes_helper.rb +76 -0
- data/lib/mtncloud/cli/mixins/vdi_helper.rb +246 -0
- data/lib/mtncloud/cli/mixins/whoami_helper.rb +73 -0
- data/lib/mtncloud/cli/option_parser.rb +127 -0
- data/lib/mtncloud/cli/option_types.rb +1622 -0
- data/lib/mtncloud/cli/version.rb +6 -0
- data/lib/mtncloud/cli.rb +105 -0
- data/lib/mtncloud/currency.rb +184 -0
- data/lib/mtncloud/ext/hash.rb +109 -0
- data/lib/mtncloud/ext/nil_class.rb +5 -0
- data/lib/mtncloud/ext/rest_client.rb +37 -0
- data/lib/mtncloud/ext/string.rb +66 -0
- data/lib/mtncloud/formatters.rb +511 -0
- data/lib/mtncloud/logging.rb +185 -0
- data/lib/mtncloud/morpkg.rb +119 -0
- data/lib/mtncloud/rest_client.rb +104 -0
- data/lib/mtncloud/routes.rb +304 -0
- data/lib/mtncloud/terminal.rb +528 -0
- data/lib/mtncloud/util.rb +29 -0
- data/lib/mtncloud.rb +5 -0
- data/mtncloud-cli.gemspec +38 -0
- data/test/api/affinity_groups_interface_test.rb +43 -0
- data/test/api/clients_interface_test.rb +23 -0
- data/test/api/clouds_interface_test.rb +67 -0
- data/test/api/containers_interface_test.rb +68 -0
- data/test/api/host_vm_groups_interface_test.rb +35 -0
- data/test/api/instances_interface_test.rb +22 -0
- data/test/api/network_routers_interface_test.rb +22 -0
- data/test/api/systems_interface_test.rb +26 -0
- data/test/api/whoami_interface_test.rb +14 -0
- data/test/branding_test.rb +160 -0
- data/test/cli/access_token_test.rb +36 -0
- data/test/cli/affinity_groups_cloud_cluster_scope_test.rb +270 -0
- data/test/cli/affinity_groups_cluster_scope_test.rb +171 -0
- data/test/cli/affinity_groups_test.rb +57 -0
- data/test/cli/affinity_groups_violations_scope_test.rb +141 -0
- data/test/cli/affinity_helper_test.rb +367 -0
- data/test/cli/auth_test.rb +88 -0
- data/test/cli/backups_test.rb +212 -0
- data/test/cli/cli_test.rb +48 -0
- data/test/cli/clients_test.rb +45 -0
- data/test/cli/clusters_uuid_test.rb +146 -0
- data/test/cli/containers_test.rb +92 -0
- data/test/cli/distributed_workers_test.rb +68 -0
- data/test/cli/help_test.rb +25 -0
- data/test/cli/host_vm_groups_cluster_scope_test.rb +187 -0
- data/test/cli/host_vm_groups_test.rb +63 -0
- data/test/cli/infrastructure_helper_cluster_resolver_test.rb +250 -0
- data/test/cli/instances_test.rb +37 -0
- data/test/cli/man_test.rb +14 -0
- data/test/cli/migrations_test.rb +39 -0
- data/test/cli/network_routers_test.rb +65 -0
- data/test/cli/remote_test.rb +89 -0
- data/test/cli/roles_test.rb +47 -0
- data/test/cli/shell_test.rb +81 -0
- data/test/cli/storage_volumes_test.rb +79 -0
- data/test/cli/systems_test.rb +206 -0
- data/test/cli/version_test.rb +23 -0
- data/test/cli/view_test.rb +55 -0
- data/test/cli/whoami_test.rb +17 -0
- data/test/mtncloud_test.rb +16 -0
- data/test/test_case.rb +342 -0
- data/test/test_config.rb +137 -0
- data/test/test_data_helper.rb +97 -0
- metadata +807 -0
|
@@ -0,0 +1,2986 @@
|
|
|
1
|
+
require 'mtncloud/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class MtnCloud::Cli::Hosts
|
|
4
|
+
include MtnCloud::Cli::CliCommand
|
|
5
|
+
include MtnCloud::Cli::AccountsHelper
|
|
6
|
+
include MtnCloud::Cli::ProcessesHelper
|
|
7
|
+
include MtnCloud::Cli::ProvisioningHelper
|
|
8
|
+
include MtnCloud::Cli::LogsHelper
|
|
9
|
+
set_command_name :hosts
|
|
10
|
+
set_command_description "View and manage hosts (servers)."
|
|
11
|
+
register_subcommands :list, :count, :get, :view, :stats, :add, :update, :remove, :logs, :start, :stop, :resize, :restart,
|
|
12
|
+
:run_workflow, :make_managed, :upgrade_agent, :snapshots, :software, :software_sync, :update_network_label,
|
|
13
|
+
{:'types' => :list_types},
|
|
14
|
+
{:exec => :execution_request},
|
|
15
|
+
:wiki, :update_wiki,
|
|
16
|
+
:maintenance, :leave_maintenance, :placement,
|
|
17
|
+
:list_devices, :assign_device, :detach_device, :attach_device,
|
|
18
|
+
:snapshot, :create_linked_clone
|
|
19
|
+
alias_subcommand :details, :get
|
|
20
|
+
set_default_subcommand :list
|
|
21
|
+
|
|
22
|
+
def initialize()
|
|
23
|
+
# @appliance_name, @appliance_url = MtnCloud::Cli::Remote.active_appliance
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def connect(opts)
|
|
27
|
+
@api_client = establish_remote_appliance_connection(opts)
|
|
28
|
+
@accounts_interface = @api_client.accounts
|
|
29
|
+
@account_users_interface = @api_client.account_users
|
|
30
|
+
@clouds_interface = @api_client.clouds
|
|
31
|
+
@options_interface = @api_client.options
|
|
32
|
+
@tasks_interface = @api_client.tasks
|
|
33
|
+
@task_sets_interface = @api_client.task_sets
|
|
34
|
+
@servers_interface = @api_client.servers
|
|
35
|
+
@server_types_interface = @api_client.server_types
|
|
36
|
+
@provision_types_interface = @api_client.provision_types
|
|
37
|
+
@logs_interface = @api_client.logs
|
|
38
|
+
@accounts_interface = @api_client.accounts
|
|
39
|
+
@active_group_id = MtnCloud::Cli::Groups.active_groups[@appliance_name]
|
|
40
|
+
@execution_request_interface = @api_client.execution_request
|
|
41
|
+
@clusters_interface = @api_client.clusters
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def handle(args)
|
|
45
|
+
handle_subcommand(args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def list(args)
|
|
49
|
+
options = {}
|
|
50
|
+
params = {}
|
|
51
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
52
|
+
opts.banner = subcommand_usage()
|
|
53
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
|
54
|
+
options[:group] = val
|
|
55
|
+
end
|
|
56
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
|
57
|
+
options[:cloud] = val
|
|
58
|
+
end
|
|
59
|
+
opts.on( '-M', '--managed', "Show only Managed Servers" ) do |val|
|
|
60
|
+
params[:managed] = true
|
|
61
|
+
end
|
|
62
|
+
opts.on( '-U', '--unmanaged', "Show only Unmanaged Servers" ) do |val|
|
|
63
|
+
params[:managed] = false
|
|
64
|
+
end
|
|
65
|
+
opts.on( '-t', '--type TYPE', "Show only Certain Server Types" ) do |val|
|
|
66
|
+
params[:serverType] = val
|
|
67
|
+
end
|
|
68
|
+
opts.on( '-p', '--power STATE', "Filter by Power Status" ) do |val|
|
|
69
|
+
params[:powerState] = val
|
|
70
|
+
end
|
|
71
|
+
opts.on( '-i', '--ip IPADDRESS', "Filter by IP Address" ) do |val|
|
|
72
|
+
params[:ip] = val
|
|
73
|
+
end
|
|
74
|
+
opts.on( '--cluster CLUSTER', '--cluster CLUSTER', "Filter by Cluster Name or ID" ) do |val|
|
|
75
|
+
# params[:clusterId] = val
|
|
76
|
+
options[:cluster] = val
|
|
77
|
+
end
|
|
78
|
+
opts.on( '--parent HOST', "Parent Host / Hypervisor Name or ID" ) do |val|
|
|
79
|
+
options[:parent_server_id] = val
|
|
80
|
+
end
|
|
81
|
+
opts.on( '--plan NAME', String, "Filter by Plan name(s)" ) do |val|
|
|
82
|
+
# commas used in names a lot so use --plan one --plan two
|
|
83
|
+
params['plan'] ||= []
|
|
84
|
+
params['plan'] << val
|
|
85
|
+
end
|
|
86
|
+
opts.on( '--plan-id ID', String, "Filter by Plan id(s)" ) do |val|
|
|
87
|
+
params['planId'] = parse_id_list(val)
|
|
88
|
+
end
|
|
89
|
+
opts.on( '--plan-code CODE', String, "Filter by Plan code(s)" ) do |val|
|
|
90
|
+
params['planCode'] = parse_id_list(val)
|
|
91
|
+
end
|
|
92
|
+
opts.on('--vm', "Show only virtual machines" ) do
|
|
93
|
+
params[:vm] = true
|
|
94
|
+
end
|
|
95
|
+
opts.on('--hypervisor', "Show only VM Hypervisors" ) do
|
|
96
|
+
params[:vmHypervisor] = true
|
|
97
|
+
end
|
|
98
|
+
opts.on('--container', "Show only Container Hypervisors" ) do
|
|
99
|
+
params[:containerHypervisor] = true
|
|
100
|
+
end
|
|
101
|
+
opts.on('--baremetal', "Show only Baremetal Servers" ) do
|
|
102
|
+
params[:bareMetalHost] = true
|
|
103
|
+
end
|
|
104
|
+
opts.on('--status STATUS', String, "Filter by Status" ) do |val|
|
|
105
|
+
params[:status] = val
|
|
106
|
+
end
|
|
107
|
+
opts.on('--agent', "Show only Servers with the agent installed" ) do
|
|
108
|
+
params[:agentInstalled] = true
|
|
109
|
+
end
|
|
110
|
+
opts.on('--noagent', "Show only Servers with No agent" ) do
|
|
111
|
+
params[:agentInstalled] = false
|
|
112
|
+
end
|
|
113
|
+
opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
|
|
114
|
+
options[:created_by] = val
|
|
115
|
+
end
|
|
116
|
+
opts.on('--include-tenants','--include-tenants', "Include sub tenant servers. The default is true for this endpoint.") do
|
|
117
|
+
options[:include_tenants] = true
|
|
118
|
+
params['includeTenants'] = true
|
|
119
|
+
end
|
|
120
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
|
121
|
+
options[:tenant] = val
|
|
122
|
+
end
|
|
123
|
+
opts.on('-l', '--labels LABEL', String, "Filter by labels, can match any of the values") do |val|
|
|
124
|
+
add_query_parameter(params, 'labels', parse_labels(val))
|
|
125
|
+
end
|
|
126
|
+
opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
|
|
127
|
+
add_query_parameter(params, 'allLabels', parse_labels(val))
|
|
128
|
+
end
|
|
129
|
+
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
|
130
|
+
val.split(",").each do |value_pair|
|
|
131
|
+
k,v = value_pair.strip.split("=")
|
|
132
|
+
options[:tags] ||= {}
|
|
133
|
+
options[:tags][k] ||= []
|
|
134
|
+
options[:tags][k] << (v || '')
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
opts.on('--tag-compliant', "Displays only servers that are valid according to applied tag policies. Does not show servers that do not have tag policies." ) do
|
|
138
|
+
params[:tagCompliant] = true
|
|
139
|
+
end
|
|
140
|
+
opts.on('--non-tag-compliant', "Displays only servers with tag compliance warnings." ) do
|
|
141
|
+
params[:tagCompliant] = false
|
|
142
|
+
end
|
|
143
|
+
opts.on('--stats', "Display values for memory and storage usage used / max values." ) do
|
|
144
|
+
options[:stats] = true
|
|
145
|
+
end
|
|
146
|
+
opts.on('-a', '--details', "Display all details: hostname, private ip, plan, stats, etc." ) do
|
|
147
|
+
options[:details] = true
|
|
148
|
+
end
|
|
149
|
+
build_standard_list_options(opts, options)
|
|
150
|
+
opts.footer = "List hosts."
|
|
151
|
+
end
|
|
152
|
+
optparse.parse!(args)
|
|
153
|
+
connect(options)
|
|
154
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
|
155
|
+
if args.count > 0
|
|
156
|
+
options[:phrase] = args.join(" ")
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
params.merge!(parse_list_options(options))
|
|
160
|
+
account = nil
|
|
161
|
+
if options[:tenant]
|
|
162
|
+
account = find_account_by_name_or_id(options[:tenant])
|
|
163
|
+
if account.nil?
|
|
164
|
+
return 1
|
|
165
|
+
else
|
|
166
|
+
params['accountId'] = account['id']
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
|
170
|
+
if group
|
|
171
|
+
params['siteId'] = group['id']
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# argh, this doesn't work because group_id is required for options/clouds
|
|
175
|
+
# cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
|
|
176
|
+
cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
|
|
177
|
+
if cloud
|
|
178
|
+
params['zoneId'] = cloud['id']
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if options[:created_by]
|
|
182
|
+
created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:created_by])
|
|
183
|
+
return if created_by_ids.nil?
|
|
184
|
+
params['createdBy'] = created_by_ids
|
|
185
|
+
# params['ownerId'] = created_by_ids # 4.2.1+
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
cluster = nil
|
|
189
|
+
if options[:cluster]
|
|
190
|
+
if options[:cluster].to_s =~ /\A\d{1,}\Z/
|
|
191
|
+
params['clusterId'] = options[:cluster]
|
|
192
|
+
else
|
|
193
|
+
cluster = find_cluster_by_name_or_id(options[:cluster])
|
|
194
|
+
return 1 if cluster.nil?
|
|
195
|
+
params['clusterId'] = cluster['id']
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
parent_hosts = nil
|
|
199
|
+
if options[:parent_server_id]
|
|
200
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
201
|
+
find_host_by_name_or_id(parent_server_id)
|
|
202
|
+
end
|
|
203
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
204
|
+
end
|
|
205
|
+
params['labels'] = options[:labels] if options[:labels]
|
|
206
|
+
if options[:tags] && !options[:tags].empty?
|
|
207
|
+
options[:tags].each do |k,v|
|
|
208
|
+
params['tags.' + k] = v
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
@servers_interface.setopts(options)
|
|
213
|
+
if options[:dry_run]
|
|
214
|
+
print_dry_run @servers_interface.dry.list(params)
|
|
215
|
+
return
|
|
216
|
+
end
|
|
217
|
+
json_response = @servers_interface.list(params)
|
|
218
|
+
|
|
219
|
+
# merge stats to be nice here..
|
|
220
|
+
all_stats = json_response['stats']
|
|
221
|
+
if options[:include_fields] || options[:all_fields]
|
|
222
|
+
if json_response['servers']
|
|
223
|
+
if all_stats
|
|
224
|
+
json_response['servers'].each do |it|
|
|
225
|
+
it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
render_response(json_response, options, "servers") do
|
|
231
|
+
|
|
232
|
+
servers = json_response['servers']
|
|
233
|
+
multi_tenant = json_response['multiTenant'] == true
|
|
234
|
+
title = "Hosts"
|
|
235
|
+
subtitles = []
|
|
236
|
+
if account
|
|
237
|
+
subtitles << "Tenant: #{account['name']}".strip
|
|
238
|
+
end
|
|
239
|
+
if group
|
|
240
|
+
subtitles << "Group: #{group['name']}".strip
|
|
241
|
+
end
|
|
242
|
+
if cloud
|
|
243
|
+
subtitles << "Cloud: #{cloud['name']}".strip
|
|
244
|
+
end
|
|
245
|
+
if cluster
|
|
246
|
+
subtitles << "Cluster: #{cluster['name']}".strip
|
|
247
|
+
elsif params['clusterId']
|
|
248
|
+
subtitles << "Cluster: #{params['clusterId']}".strip
|
|
249
|
+
end
|
|
250
|
+
if parent_hosts
|
|
251
|
+
subtitles << "Parent Host: #{parent_hosts.collect {|it| it['name'] }.join(", ")}".strip
|
|
252
|
+
end
|
|
253
|
+
subtitles += parse_list_subtitles(options)
|
|
254
|
+
print_h1 title, subtitles, options
|
|
255
|
+
if servers.empty?
|
|
256
|
+
print cyan,"No hosts found.",reset,"\n"
|
|
257
|
+
else
|
|
258
|
+
# print_servers_table(servers)
|
|
259
|
+
# server returns stats in a separate key stats => {"id" => {} }
|
|
260
|
+
# the id is a string right now..for some reason..
|
|
261
|
+
all_stats = json_response['stats'] || {}
|
|
262
|
+
servers.each do |it|
|
|
263
|
+
found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
|
|
264
|
+
if found_stats
|
|
265
|
+
if !it['stats']
|
|
266
|
+
it['stats'] = found_stats # || {}
|
|
267
|
+
else
|
|
268
|
+
it['stats'] = found_stats.merge!(it['stats'])
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
rows = servers.collect {|server|
|
|
274
|
+
stats = server['stats']
|
|
275
|
+
|
|
276
|
+
if !stats['maxMemory'] && (stats['usedMemory'] || stats['freeMemory'])
|
|
277
|
+
stats['maxMemory'] = stats['usedMemory'].to_i + stats['freeMemory'].to_i
|
|
278
|
+
end
|
|
279
|
+
cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
|
|
280
|
+
memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
|
|
281
|
+
storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
|
|
282
|
+
if options[:details] || options[:stats]
|
|
283
|
+
if stats['maxMemory'] && stats['maxMemory'].to_i != 0
|
|
284
|
+
memory_usage_str = memory_usage_str + cyan + format_bytes_short(stats['usedMemory']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxMemory']).strip
|
|
285
|
+
end
|
|
286
|
+
if stats['maxStorage'] && stats['maxStorage'].to_i != 0
|
|
287
|
+
storage_usage_str = storage_usage_str + cyan + format_bytes_short(stats['usedStorage']).strip.rjust(8, ' ') + " / " + format_bytes_short(stats['maxStorage']).strip
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
row = {
|
|
291
|
+
id: server['id'],
|
|
292
|
+
name: server['name'],
|
|
293
|
+
external_name: server['externalName'],
|
|
294
|
+
hostname: server['hostname'],
|
|
295
|
+
platform: server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A',
|
|
296
|
+
type: server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged',
|
|
297
|
+
tenant: server['account'] ? server['account']['name'] : server['accountId'],
|
|
298
|
+
owner: server['owner'] ? server['owner']['username'] : server['owner'],
|
|
299
|
+
cloud: server['zone'] ? server['zone']['name'] : '',
|
|
300
|
+
plan: server['plan'] ? server['plan']['name'] : '',
|
|
301
|
+
ip: server['externalIp'],
|
|
302
|
+
internal_ip: server['internalIp'],
|
|
303
|
+
nodes: server['containers'] ? server['containers'].size : '',
|
|
304
|
+
# status: format_server_status(server, cyan),
|
|
305
|
+
status: (options[:details]||options[:all_fields]) ? format_server_status(server, cyan) : format_server_status_friendly(server, cyan),
|
|
306
|
+
power: format_server_power_state(server, cyan),
|
|
307
|
+
cpu: cpu_usage_str + cyan,
|
|
308
|
+
memory: memory_usage_str + cyan,
|
|
309
|
+
storage: storage_usage_str + cyan,
|
|
310
|
+
created: format_local_dt(server['dateCreated']),
|
|
311
|
+
updated: format_local_dt(server['lastUpdated']),
|
|
312
|
+
}
|
|
313
|
+
row
|
|
314
|
+
}
|
|
315
|
+
# columns = [:id, :name, :type, :cloud, :ip, :internal_ip, :nodes, :status, :power]
|
|
316
|
+
columns = {
|
|
317
|
+
"ID" => :id,
|
|
318
|
+
"Name" => :name,
|
|
319
|
+
"External Name" => :external_name,
|
|
320
|
+
"Hostname" => :hostname,
|
|
321
|
+
"Type" => :type,
|
|
322
|
+
"Cloud" => :cloud,
|
|
323
|
+
"Owner" => :owner,
|
|
324
|
+
"Tenant" => :tenant,
|
|
325
|
+
"Plan" => :plan,
|
|
326
|
+
"IP" => :ip,
|
|
327
|
+
"Private IP" => :internal_ip,
|
|
328
|
+
"Nodes" => :nodes,
|
|
329
|
+
"Status" => :status,
|
|
330
|
+
"Power" => :power,
|
|
331
|
+
"CPU" => :cpu,
|
|
332
|
+
"Memory" => :memory,
|
|
333
|
+
"Storage" => :storage,
|
|
334
|
+
"Created" => :created,
|
|
335
|
+
"Updated" => :updated,
|
|
336
|
+
}
|
|
337
|
+
if options[:details] != true
|
|
338
|
+
columns.delete("External Name")
|
|
339
|
+
columns.delete("Hostname")
|
|
340
|
+
columns.delete("Plan")
|
|
341
|
+
columns.delete("Private IP")
|
|
342
|
+
columns.delete("Power")
|
|
343
|
+
columns.delete("Created")
|
|
344
|
+
columns.delete("Updated")
|
|
345
|
+
end
|
|
346
|
+
# hide External Name if there are none
|
|
347
|
+
if !servers.find {|it| it['externalName'] && it['externalName'] != it['name']}
|
|
348
|
+
columns.delete("External Name")
|
|
349
|
+
end
|
|
350
|
+
if !multi_tenant
|
|
351
|
+
columns.delete("Tenant")
|
|
352
|
+
end
|
|
353
|
+
# columns += [:cpu, :memory, :storage]
|
|
354
|
+
# # custom pretty table columns ...
|
|
355
|
+
# if options[:include_fields]
|
|
356
|
+
# columns = options[:include_fields]
|
|
357
|
+
# end
|
|
358
|
+
print cyan
|
|
359
|
+
print as_pretty_table(rows, columns.upcase_keys!, options)
|
|
360
|
+
print reset
|
|
361
|
+
print_results_pagination(json_response)
|
|
362
|
+
end
|
|
363
|
+
print reset,"\n"
|
|
364
|
+
end
|
|
365
|
+
return 0, nil
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def count(args)
|
|
369
|
+
params = {}
|
|
370
|
+
options = {}
|
|
371
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
372
|
+
opts.banner = subcommand_usage("[options]")
|
|
373
|
+
opts.on( '--tenant TENANT', "Tenant Name or ID" ) do |val|
|
|
374
|
+
options[:tenant] = val
|
|
375
|
+
end
|
|
376
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
|
377
|
+
options[:group] = val
|
|
378
|
+
end
|
|
379
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
|
380
|
+
options[:cloud] = val
|
|
381
|
+
end
|
|
382
|
+
opts.on( '-M', '--managed', "Show only Managed Servers" ) do |val|
|
|
383
|
+
params[:managed] = true
|
|
384
|
+
end
|
|
385
|
+
opts.on( '-U', '--unmanaged', "Show only Unmanaged Servers" ) do |val|
|
|
386
|
+
params[:managed] = false
|
|
387
|
+
end
|
|
388
|
+
opts.on( '-t', '--type TYPE', "Show only Certain Server Types" ) do |val|
|
|
389
|
+
params[:serverType] = val
|
|
390
|
+
end
|
|
391
|
+
opts.on( '-p', '--power STATE', "Filter by Power Status" ) do |val|
|
|
392
|
+
params[:powerState] = val
|
|
393
|
+
end
|
|
394
|
+
opts.on( '-i', '--ip IPADDRESS', "Filter by IP Address" ) do |val|
|
|
395
|
+
params[:ip] = val
|
|
396
|
+
end
|
|
397
|
+
opts.on( '--cluster CLUSTER', '--cluster CLUSTER', "Filter by Cluster Name or ID" ) do |val|
|
|
398
|
+
# params[:clusterId] = val
|
|
399
|
+
options[:cluster] = val
|
|
400
|
+
end
|
|
401
|
+
opts.on( '--parent HOST', "Parent Host / Hypervisor Name or ID" ) do |val|
|
|
402
|
+
options[:parent_server_id] = val
|
|
403
|
+
end
|
|
404
|
+
opts.on('--vm', "Show only virtual machines" ) do
|
|
405
|
+
params[:vm] = true
|
|
406
|
+
end
|
|
407
|
+
opts.on('--hypervisor', "Show only VM Hypervisors" ) do
|
|
408
|
+
params[:vmHypervisor] = true
|
|
409
|
+
end
|
|
410
|
+
opts.on('--container', "Show only Container Hypervisors" ) do
|
|
411
|
+
params[:containerHypervisor] = true
|
|
412
|
+
end
|
|
413
|
+
opts.on('--baremetal', "Show only Baremetal Servers" ) do
|
|
414
|
+
params[:bareMetalHost] = true
|
|
415
|
+
end
|
|
416
|
+
opts.on('--status STATUS', "Filter by Status" ) do |val|
|
|
417
|
+
params[:status] = val
|
|
418
|
+
end
|
|
419
|
+
opts.on('--agent', "Show only Servers with the agent installed" ) do
|
|
420
|
+
params[:agentInstalled] = true
|
|
421
|
+
end
|
|
422
|
+
opts.on('--noagent', "Show only Servers with No agent" ) do
|
|
423
|
+
params[:agentInstalled] = false
|
|
424
|
+
end
|
|
425
|
+
opts.on( '--created-by USER', "Created By User Username or ID" ) do |val|
|
|
426
|
+
options[:created_by] = val
|
|
427
|
+
end
|
|
428
|
+
opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
|
|
429
|
+
options[:phrase] = phrase
|
|
430
|
+
end
|
|
431
|
+
build_common_options(opts, options, [:query, :remote, :dry_run])
|
|
432
|
+
opts.footer = "Get the number of hosts."
|
|
433
|
+
end
|
|
434
|
+
optparse.parse!(args)
|
|
435
|
+
connect(options)
|
|
436
|
+
begin
|
|
437
|
+
params.merge!(parse_list_options(options))
|
|
438
|
+
account = nil
|
|
439
|
+
if options[:tenant]
|
|
440
|
+
account = find_account_by_name_or_id(options[:tenant])
|
|
441
|
+
if account.nil?
|
|
442
|
+
return 1
|
|
443
|
+
else
|
|
444
|
+
params['accountId'] = account['id']
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
|
448
|
+
if group
|
|
449
|
+
params['siteId'] = group['id']
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# argh, this doesn't work because group_id is required for options/clouds
|
|
453
|
+
# cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
|
|
454
|
+
cloud = options[:cloud] ? find_zone_by_name_or_id(nil, options[:cloud]) : nil
|
|
455
|
+
if cloud
|
|
456
|
+
params['zoneId'] = cloud['id']
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
if options[:created_by]
|
|
460
|
+
created_by_ids = find_all_user_ids(account ? account['id'] : nil, options[:created_by])
|
|
461
|
+
return if created_by_ids.nil?
|
|
462
|
+
params['createdBy'] = created_by_ids
|
|
463
|
+
# params['ownerId'] = created_by_ids # 4.2.1+
|
|
464
|
+
end
|
|
465
|
+
cluster = nil
|
|
466
|
+
if options[:cluster]
|
|
467
|
+
if options[:cluster].to_s =~ /\A\d{1,}\Z/
|
|
468
|
+
params['clusterId'] = options[:cluster]
|
|
469
|
+
else
|
|
470
|
+
cluster = find_cluster_by_name_or_id(options[:cluster])
|
|
471
|
+
return 1 if cluster.nil?
|
|
472
|
+
params['clusterId'] = cluster['id']
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
parent_hosts = nil
|
|
476
|
+
if options[:parent_server_id]
|
|
477
|
+
parent_hosts = parse_id_list(options[:parent_server_id]).collect do |parent_server_id|
|
|
478
|
+
find_host_by_name_or_id(parent_server_id)
|
|
479
|
+
end
|
|
480
|
+
params['parentServerId'] = parent_hosts.collect {|it| it['id'] }
|
|
481
|
+
end
|
|
482
|
+
@servers_interface.setopts(options)
|
|
483
|
+
if options[:dry_run]
|
|
484
|
+
print_dry_run @servers_interface.dry.list(params)
|
|
485
|
+
return
|
|
486
|
+
end
|
|
487
|
+
json_response = @servers_interface.list(params)
|
|
488
|
+
# print number only
|
|
489
|
+
if json_response['meta'] && json_response['meta']['total']
|
|
490
|
+
print cyan, json_response['meta']['total'], reset, "\n"
|
|
491
|
+
else
|
|
492
|
+
print yellow, "unknown", reset, "\n"
|
|
493
|
+
end
|
|
494
|
+
return 0
|
|
495
|
+
rescue RestClient::Exception => e
|
|
496
|
+
print_rest_exception(e, options)
|
|
497
|
+
exit 1
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def get(args)
|
|
502
|
+
options = {}
|
|
503
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
504
|
+
opts.banner = subcommand_usage("[name]")
|
|
505
|
+
opts.on( nil, '--costs', "Display Cost and Price" ) do
|
|
506
|
+
options[:include_costs] = true
|
|
507
|
+
end
|
|
508
|
+
opts.on('--refresh [SECONDS]', String, "Refresh until status is provisioned,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
|
509
|
+
options[:refresh_until_status] ||= "provisioned,failed"
|
|
510
|
+
if !val.to_s.empty?
|
|
511
|
+
options[:refresh_interval] = val.to_f
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
opts.on('--refresh-until STATUS', String, "Refresh until a specified status is reached.") do |val|
|
|
515
|
+
options[:refresh_until_status] = val.to_s.downcase
|
|
516
|
+
end
|
|
517
|
+
opts.on('--include-tenants','--include-tenants', "Include sub tenant servers when finding server by name") do
|
|
518
|
+
options[:include_tenants] = true
|
|
519
|
+
end
|
|
520
|
+
build_standard_get_options(opts, options)
|
|
521
|
+
end
|
|
522
|
+
optparse.parse!(args)
|
|
523
|
+
if args.count < 1
|
|
524
|
+
puts optparse
|
|
525
|
+
exit 1
|
|
526
|
+
end
|
|
527
|
+
connect(options)
|
|
528
|
+
id_list = parse_id_list(args)
|
|
529
|
+
return run_command_for_each_arg(id_list) do |arg|
|
|
530
|
+
_get(arg, options)
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def _get(arg, options)
|
|
535
|
+
@servers_interface.setopts(options)
|
|
536
|
+
if options[:dry_run]
|
|
537
|
+
if arg.to_s =~ /\A\d{1,}\Z/
|
|
538
|
+
print_dry_run @servers_interface.dry.get(arg.to_i)
|
|
539
|
+
else
|
|
540
|
+
print_dry_run @servers_interface.dry.list({name: arg})
|
|
541
|
+
end
|
|
542
|
+
return
|
|
543
|
+
end
|
|
544
|
+
json_response = nil
|
|
545
|
+
if arg.to_s =~ /\A\d{1,}\Z/
|
|
546
|
+
json_response = @servers_interface.get(arg.to_i)
|
|
547
|
+
else
|
|
548
|
+
server = find_host_by_name_or_id(arg, options[:include_tenants])
|
|
549
|
+
json_response = @servers_interface.get(server['id'])
|
|
550
|
+
# json_response = {"server" => server} need stats
|
|
551
|
+
end
|
|
552
|
+
render_response(json_response, options, "server") do
|
|
553
|
+
server = json_response['server'] || json_response['host'] || {}
|
|
554
|
+
#stats = server['stats'] || json_response['stats'] || {}
|
|
555
|
+
stats = json_response['stats'] || {}
|
|
556
|
+
tags = server['tags'] || server['metadata']
|
|
557
|
+
title = "Host Details"
|
|
558
|
+
print_h1 title, [], options
|
|
559
|
+
print cyan
|
|
560
|
+
server_columns = {
|
|
561
|
+
"ID" => 'id',
|
|
562
|
+
"Name" => 'name',
|
|
563
|
+
"Hostname" => 'hostname',
|
|
564
|
+
"Description" => 'description',
|
|
565
|
+
"Labels" => lambda {|it| format_list(it['labels']) rescue '' },
|
|
566
|
+
"Tags" => lambda {|it| tags ? format_metadata(tags) : '' },
|
|
567
|
+
"Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
|
|
568
|
+
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
|
569
|
+
#"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
|
570
|
+
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
|
571
|
+
"IP" => lambda {|it| it['externalIp'] },
|
|
572
|
+
"Private IP" => lambda {|it| it['internalIp'] },
|
|
573
|
+
"Type" => lambda {|it| it['computeServerType'] ? it['computeServerType']['name'] : 'unmanaged' },
|
|
574
|
+
"Platform" => lambda {|it| it['serverOs'] ? it['serverOs']['name'].upcase : 'N/A' },
|
|
575
|
+
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
|
576
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
577
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
578
|
+
"Agent" => lambda {|it| it['agentInstalled'] ? "#{server['agentVersion'] || ''} updated at #{format_local_dt(server['lastAgentUpdate'])}" : '(not installed)' },
|
|
579
|
+
"Nodes" => lambda {|it| it['containers'] ? it['containers'].size : 0 },
|
|
580
|
+
# "Status" => lambda {|it| format_server_status(it) },
|
|
581
|
+
# "Power" => lambda {|it| format_server_power_state(it) },
|
|
582
|
+
"Managed" => lambda {|it| it['computeServerType'] ? it['computeServerType']['managed'] : ''},
|
|
583
|
+
"Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : ''},
|
|
584
|
+
"Status" => lambda {|it| format_server_status_friendly(it) } # combo
|
|
585
|
+
}
|
|
586
|
+
server_columns.delete("Hostname") if server['hostname'].to_s.empty? || server['hostname'] == server['name']
|
|
587
|
+
server_columns.delete("IP") if server['externalIp'].to_s.empty?
|
|
588
|
+
server_columns.delete("Private IP") if server['internalIp'].to_s.empty?
|
|
589
|
+
# server_columns.delete("Tenant") if multi_tenant != true
|
|
590
|
+
server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
|
|
591
|
+
server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
|
|
592
|
+
server_columns.delete("Labels") if server['labels'].nil? || server['labels'].empty?
|
|
593
|
+
server_columns.delete("Instance") if server['instance'].nil?
|
|
594
|
+
|
|
595
|
+
print_description_list(server_columns, server)
|
|
596
|
+
|
|
597
|
+
if server['statusMessage']
|
|
598
|
+
print_h2 "Status Message", options
|
|
599
|
+
if server['status'] == 'failed'
|
|
600
|
+
print red, server['statusMessage'], reset
|
|
601
|
+
else
|
|
602
|
+
print server['statusMessage']
|
|
603
|
+
end
|
|
604
|
+
print "\n"
|
|
605
|
+
end
|
|
606
|
+
if server['errorMessage']
|
|
607
|
+
print_h2 "Error Message", options
|
|
608
|
+
print red, server['errorMessage'], reset, "\n"
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
print_h2 "Host Usage", options
|
|
612
|
+
print_stats_usage(stats)
|
|
613
|
+
|
|
614
|
+
if options[:include_costs]
|
|
615
|
+
print_h2 "Host Cost"
|
|
616
|
+
cost_columns = {
|
|
617
|
+
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
618
|
+
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
|
619
|
+
}
|
|
620
|
+
print_description_list(cost_columns, server)
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
print reset, "\n"
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
# refresh until a status is reached
|
|
627
|
+
if options[:refresh_until_status]
|
|
628
|
+
if options[:refresh_interval].nil? || options[:refresh_interval].to_f < 0
|
|
629
|
+
options[:refresh_interval] = default_refresh_interval
|
|
630
|
+
end
|
|
631
|
+
statuses = options[:refresh_until_status].to_s.downcase.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
|
|
632
|
+
if !statuses.include?(server['status'])
|
|
633
|
+
print cyan
|
|
634
|
+
print cyan, "Refreshing in #{options[:refresh_interval] > 1 ? options[:refresh_interval].to_i : options[:refresh_interval]} seconds"
|
|
635
|
+
sleep_with_dots(options[:refresh_interval])
|
|
636
|
+
print "\n"
|
|
637
|
+
_get(arg, options)
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
end
|
|
641
|
+
return 0, nil
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
def stats(args)
|
|
645
|
+
options = {}
|
|
646
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
647
|
+
opts.banner = subcommand_usage("[name]")
|
|
648
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
|
649
|
+
end
|
|
650
|
+
optparse.parse!(args)
|
|
651
|
+
if args.count < 1
|
|
652
|
+
puts optparse
|
|
653
|
+
exit 1
|
|
654
|
+
end
|
|
655
|
+
connect(options)
|
|
656
|
+
ids = args
|
|
657
|
+
id_list = parse_id_list(args)
|
|
658
|
+
return run_command_for_each_arg(id_list) do |arg|
|
|
659
|
+
_stats(arg, options)
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
def _stats(arg, options)
|
|
664
|
+
begin
|
|
665
|
+
@servers_interface.setopts(options)
|
|
666
|
+
if options[:dry_run]
|
|
667
|
+
if arg.to_s =~ /\A\d{1,}\Z/
|
|
668
|
+
print_dry_run @servers_interface.dry.get(arg.to_i)
|
|
669
|
+
else
|
|
670
|
+
print_dry_run @servers_interface.dry.list({name: arg})
|
|
671
|
+
end
|
|
672
|
+
return
|
|
673
|
+
end
|
|
674
|
+
server = find_host_by_name_or_id(arg)
|
|
675
|
+
json_response = @servers_interface.get(server['id'])
|
|
676
|
+
if options[:json]
|
|
677
|
+
puts as_json(json_response, options, "stats")
|
|
678
|
+
return 0
|
|
679
|
+
elsif options[:yaml]
|
|
680
|
+
puts as_yaml(json_response, options, "stats")
|
|
681
|
+
return 0
|
|
682
|
+
elsif options[:csv]
|
|
683
|
+
puts records_as_csv([json_response['stats']], options)
|
|
684
|
+
return 0
|
|
685
|
+
end
|
|
686
|
+
server = json_response['server']
|
|
687
|
+
#stats = server['stats'] || json_response['stats'] || {}
|
|
688
|
+
stats = json_response['stats'] || {}
|
|
689
|
+
title = "Host Stats: #{server['name']} (#{server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged'})"
|
|
690
|
+
print_h1 title, [], options
|
|
691
|
+
puts cyan + "Power: ".rjust(12) + format_server_power_state(server).to_s
|
|
692
|
+
puts cyan + "Status: ".rjust(12) + format_server_status(server).to_s
|
|
693
|
+
puts cyan + "Nodes: ".rjust(12) + (server['containers'] ? server['containers'].size : '').to_s
|
|
694
|
+
#print_h2 "Host Usage", options
|
|
695
|
+
print_stats_usage(stats, {label_width: 10})
|
|
696
|
+
|
|
697
|
+
print reset, "\n"
|
|
698
|
+
return 0
|
|
699
|
+
rescue RestClient::Exception => e
|
|
700
|
+
print_rest_exception(e, options)
|
|
701
|
+
exit 1
|
|
702
|
+
end
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def logs(args)
|
|
706
|
+
options = {}
|
|
707
|
+
params = {}
|
|
708
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
709
|
+
opts.banner = subcommand_usage("[name]")
|
|
710
|
+
opts.on('--start TIMESTAMP','--start TIMESTAMP', "Start timestamp. Default is 30 days ago.") do |val|
|
|
711
|
+
options[:start] = parse_time(val) #.utc.iso8601
|
|
712
|
+
end
|
|
713
|
+
opts.on('--end TIMESTAMP','--end TIMESTAMP', "End timestamp. Default is now.") do |val|
|
|
714
|
+
options[:end] = parse_time(val) #.utc.iso8601
|
|
715
|
+
end
|
|
716
|
+
opts.on('--level VALUE', String, "Log Level. DEBUG,INFO,WARN,ERROR") do |val|
|
|
717
|
+
params['level'] = params['level'] ? [params['level'], val].flatten : [val]
|
|
718
|
+
end
|
|
719
|
+
opts.on('--table', '--table', "Format ouput as a table.") do
|
|
720
|
+
options[:table] = true
|
|
721
|
+
end
|
|
722
|
+
opts.on('-a', '--all', "Display all details: entire message." ) do
|
|
723
|
+
options[:details] = true
|
|
724
|
+
end
|
|
725
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
|
726
|
+
end
|
|
727
|
+
optparse.parse!(args)
|
|
728
|
+
if args.count < 1
|
|
729
|
+
puts optparse
|
|
730
|
+
exit 1
|
|
731
|
+
end
|
|
732
|
+
connect(options)
|
|
733
|
+
begin
|
|
734
|
+
server = find_host_by_name_or_id(args[0])
|
|
735
|
+
params['level'] = params['level'].collect {|it| it.to_s.upcase }.join('|') if params['level'] # api works with INFO|WARN
|
|
736
|
+
params.merge!(parse_list_options(options))
|
|
737
|
+
params['query'] = params.delete('phrase') if params['phrase']
|
|
738
|
+
params['order'] = params['direction'] unless params['direction'].nil? # old api version expects order instead of direction
|
|
739
|
+
params['startMs'] = (options[:start].to_i * 1000) if options[:start]
|
|
740
|
+
params['endMs'] = (options[:end].to_i * 1000) if options[:end]
|
|
741
|
+
@logs_interface.setopts(options)
|
|
742
|
+
if options[:dry_run]
|
|
743
|
+
print_dry_run @logs_interface.dry.server_logs([server['id']], params)
|
|
744
|
+
return
|
|
745
|
+
end
|
|
746
|
+
json_response = @logs_interface.server_logs([server['id']], params)
|
|
747
|
+
render_result = json_response['logs'] ? render_with_format(json_response, options, 'logs') : render_with_format(json_response, options, 'data')
|
|
748
|
+
return 0 if render_result
|
|
749
|
+
|
|
750
|
+
title = "Host Logs: #{server['name']} (#{server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged'})"
|
|
751
|
+
subtitles = parse_list_subtitles(options)
|
|
752
|
+
if options[:start]
|
|
753
|
+
subtitles << "Start: #{options[:start]}".strip
|
|
754
|
+
end
|
|
755
|
+
if options[:end]
|
|
756
|
+
subtitles << "End: #{options[:end]}".strip
|
|
757
|
+
end
|
|
758
|
+
if params[:query]
|
|
759
|
+
subtitles << "Search: #{params[:query]}".strip
|
|
760
|
+
end
|
|
761
|
+
# if params['containers']
|
|
762
|
+
# subtitles << "Containers: #{params['containers']}".strip
|
|
763
|
+
# end
|
|
764
|
+
if params['level']
|
|
765
|
+
subtitles << "Level: #{params['level']}"
|
|
766
|
+
end
|
|
767
|
+
print_h1 title, subtitles, options
|
|
768
|
+
logs = json_response['data'] || json_response['logs']
|
|
769
|
+
if logs.empty?
|
|
770
|
+
print "#{cyan}No logs found.#{reset}\n"
|
|
771
|
+
else
|
|
772
|
+
print format_log_records(logs, options)
|
|
773
|
+
print_results_pagination({'meta'=>{'total'=>(json_response['total']['value'] rescue json_response['total']),'size'=>logs.size,'max'=>(json_response['max'] || options[:max]),'offset'=>(json_response['offset'] || options[:offset] || 0)}})
|
|
774
|
+
end
|
|
775
|
+
print reset, "\n"
|
|
776
|
+
return 0
|
|
777
|
+
rescue RestClient::Exception => e
|
|
778
|
+
print_rest_exception(e, options)
|
|
779
|
+
exit 1
|
|
780
|
+
end
|
|
781
|
+
end
|
|
782
|
+
|
|
783
|
+
def add(args)
|
|
784
|
+
options = {}
|
|
785
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
786
|
+
opts.banner = subcommand_usage("[cloud]", "[name]")
|
|
787
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
|
788
|
+
options[:group] = val
|
|
789
|
+
end
|
|
790
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
|
791
|
+
options[:cloud] = val
|
|
792
|
+
end
|
|
793
|
+
opts.on( '-t', '--type TYPE', "Server Type Code" ) do |val|
|
|
794
|
+
options[:server_type_code] = val
|
|
795
|
+
end
|
|
796
|
+
opts.on("--security-groups LIST", Integer, "Security Groups, comma separated list of security group IDs") do |val|
|
|
797
|
+
options[:security_groups] = val.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
|
|
798
|
+
end
|
|
799
|
+
opts.on("--storage-controller ARRAY", String, "Storage Controllers, JSON array of controller configs. Each entry accepts id, busNumber, typeId, typeName, removable, editable.") do |val|
|
|
800
|
+
options[:options] ||= {}
|
|
801
|
+
options[:options]['storageController'] = JSON.parse(val)
|
|
802
|
+
end
|
|
803
|
+
opts.on('--tags LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
|
804
|
+
options[:metadata] = val
|
|
805
|
+
end
|
|
806
|
+
opts.on('--metadata [LIST]', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
|
|
807
|
+
options[:metadata] = val
|
|
808
|
+
end
|
|
809
|
+
opts.add_hidden_option('--metadata')
|
|
810
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
|
811
|
+
options[:options]['labels'] = parse_labels(val)
|
|
812
|
+
end
|
|
813
|
+
opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
|
814
|
+
options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
|
|
815
|
+
end
|
|
816
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
|
817
|
+
end
|
|
818
|
+
optparse.parse!(args)
|
|
819
|
+
connect(options)
|
|
820
|
+
begin
|
|
821
|
+
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
822
|
+
payload = nil
|
|
823
|
+
if options[:payload]
|
|
824
|
+
payload = options[:payload]
|
|
825
|
+
#payload.deep_merge!({'server' => passed_options}) unless passed_options.empty?
|
|
826
|
+
payload.deep_merge!(passed_options) unless passed_options.empty?
|
|
827
|
+
else
|
|
828
|
+
# support old format of `hosts add CLOUD NAME`
|
|
829
|
+
if args[0]
|
|
830
|
+
options[:cloud] = args[0]
|
|
831
|
+
end
|
|
832
|
+
if args[1]
|
|
833
|
+
options[:host_name] = args[1]
|
|
834
|
+
end
|
|
835
|
+
# use active group by default
|
|
836
|
+
options[:group] ||= @active_group_id
|
|
837
|
+
|
|
838
|
+
params = {}
|
|
839
|
+
# Group
|
|
840
|
+
group_id = nil
|
|
841
|
+
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
|
842
|
+
if group
|
|
843
|
+
group_id = group["id"]
|
|
844
|
+
else
|
|
845
|
+
# print_red_alert "Group not found or specified!"
|
|
846
|
+
# exit 1
|
|
847
|
+
group_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Group', 'selectOptions' => get_available_groups(), 'required' => true, 'description' => 'Select Group.'}],options[:options],@api_client,{})
|
|
848
|
+
group_id = group_prompt['group']
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
# Cloud
|
|
852
|
+
cloud_id = nil
|
|
853
|
+
cloud = options[:cloud] ? find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud]) : nil
|
|
854
|
+
if cloud
|
|
855
|
+
cloud_id = cloud["id"]
|
|
856
|
+
else
|
|
857
|
+
available_clouds = get_available_clouds(group_id)
|
|
858
|
+
if available_clouds.empty?
|
|
859
|
+
print_red_alert "Group #{group['name']} has no available clouds"
|
|
860
|
+
exit 1
|
|
861
|
+
end
|
|
862
|
+
cloud_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'selectOptions' => available_clouds, 'required' => true, 'description' => 'Select Cloud.'}],options[:options],@api_client,{groupId: group_id})
|
|
863
|
+
cloud_id = cloud_prompt['cloud']
|
|
864
|
+
cloud = find_cloud_by_id_for_provisioning(group_id, cloud_id)
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
# Zone Type
|
|
868
|
+
cloud_type = cloud_type_for_id(cloud['zoneTypeId'])
|
|
869
|
+
|
|
870
|
+
# Server Type
|
|
871
|
+
cloud_server_types = cloud_type['serverTypes'].select{|b| b['creatable'] == true && b['containerHypervisor'] == false }.sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
|
|
872
|
+
if options[:server_type_code]
|
|
873
|
+
server_type_code = options[:server_type_code]
|
|
874
|
+
else
|
|
875
|
+
server_type_options = cloud_server_types.collect {|it| {'name' => it['name'], 'value' => it['code']} }
|
|
876
|
+
v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => "Server Type", 'selectOptions' => server_type_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a server type.'}], options[:options])
|
|
877
|
+
server_type_code = v_prompt['type']
|
|
878
|
+
end
|
|
879
|
+
server_type = cloud_server_types.find {|it| it['code'] == server_type_code }
|
|
880
|
+
if server_type.nil?
|
|
881
|
+
print_red_alert "Server Type #{server_type_code} not found for cloud #{cloud['name']}"
|
|
882
|
+
exit 1
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
# Server Name
|
|
886
|
+
host_name = nil
|
|
887
|
+
if options[:host_name]
|
|
888
|
+
host_name = options[:host_name]
|
|
889
|
+
else
|
|
890
|
+
name_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Server Name', 'type' => 'text', 'required' => true}], options[:options])
|
|
891
|
+
host_name = name_prompt['name'] || ''
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
payload = {}
|
|
895
|
+
payload.deep_merge!(passed_options) unless passed_options.empty?
|
|
896
|
+
payload.deep_merge!({'server' => {
|
|
897
|
+
'name' => host_name,
|
|
898
|
+
'zone' => {'id' => cloud['id']},
|
|
899
|
+
'computeServerType' => {'id' => server_type['id']},
|
|
900
|
+
}})
|
|
901
|
+
|
|
902
|
+
is_baremetal_host = server_type['bareMetalHost']
|
|
903
|
+
|
|
904
|
+
# Service plans do not apply during BareMetal server imports
|
|
905
|
+
has_service_plans = !is_baremetal_host
|
|
906
|
+
|
|
907
|
+
# uh ok, this actually expects config at root level, sibling of server
|
|
908
|
+
# payload.deep_merge!({'server' => passed_options}) unless passed_options.empty?
|
|
909
|
+
# prompt for service plan
|
|
910
|
+
service_plan = nil
|
|
911
|
+
if has_service_plans
|
|
912
|
+
service_plans_json = @servers_interface.service_plans({ zoneId: cloud['id'], serverTypeId: server_type["id"] })
|
|
913
|
+
service_plans = service_plans_json["plans"]
|
|
914
|
+
service_plans_dropdown = service_plans.collect { |sp| { 'name' => sp["name"], 'value' => sp["id"] } } # already sorted
|
|
915
|
+
plan_prompt = MtnCloud::Cli::OptionTypes.prompt([{ 'fieldName' => 'plan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this server' }], options[:options])
|
|
916
|
+
service_plan = service_plans.find { |sp| sp["id"] == plan_prompt['plan'].to_i }
|
|
917
|
+
payload['server']['plan'] = {'id' => service_plan['id']}
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
option_type_list = server_type['optionTypes']
|
|
921
|
+
|
|
922
|
+
# remove cpu and memory option types, which now come from the plan
|
|
923
|
+
option_type_list = reject_service_plan_option_types(option_type_list)
|
|
924
|
+
|
|
925
|
+
# need to GET provision type for optionTypes, and other settings...
|
|
926
|
+
provision_type_code = server_type["provisionType"] ? server_type["provisionType"]["code"] : nil
|
|
927
|
+
provision_type = nil
|
|
928
|
+
if provision_type_code
|
|
929
|
+
provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0]
|
|
930
|
+
if provision_type.nil?
|
|
931
|
+
print_red_alert "Provision Type not found by code #{provision_type_code}"
|
|
932
|
+
exit 1
|
|
933
|
+
end
|
|
934
|
+
else
|
|
935
|
+
provision_type = get_provision_type_for_zone_type(cloud['zoneType']['id'])
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
# prompt for resource pool
|
|
939
|
+
pool_id = nil
|
|
940
|
+
has_zone_pools = server_type["provisionType"] && server_type["provisionType"]["hasZonePools"]
|
|
941
|
+
if has_zone_pools
|
|
942
|
+
# pluck out the resourcePoolId option type to prompt for..why the heck is this even needed?
|
|
943
|
+
resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
|
944
|
+
option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
|
945
|
+
resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePool', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'optionSource' => 'zonePools', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.'}
|
|
946
|
+
resource_pool_prompt = MtnCloud::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, planId: service_plan ? service_plan["id"] : "", serverTypeId: server_type['id']})
|
|
947
|
+
resource_pool_prompt.deep_compact!
|
|
948
|
+
payload.deep_merge!(resource_pool_prompt)
|
|
949
|
+
if resource_pool_option_type['fieldContext'] && resource_pool_prompt[resource_pool_option_type['fieldContext']]
|
|
950
|
+
pool_id = resource_pool_prompt[resource_pool_option_type['fieldContext']][resource_pool_option_type['fieldName']]
|
|
951
|
+
elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
|
|
952
|
+
pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
|
|
953
|
+
end
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
if has_service_plans
|
|
957
|
+
# prompt for volumes
|
|
958
|
+
volumes = prompt_volumes(service_plan, provision_type, options, @api_client, {zoneId: cloud_id, serverTypeId: server_type['id'], siteId: group_id})
|
|
959
|
+
if !volumes.empty?
|
|
960
|
+
payload['volumes'] = volumes
|
|
961
|
+
end
|
|
962
|
+
|
|
963
|
+
if options[:options] && options[:options]['storageController']
|
|
964
|
+
payload['storageController'] = options[:options]['storageController']
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
# plan customizations
|
|
968
|
+
plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {})
|
|
969
|
+
if plan_opts && !plan_opts.empty?
|
|
970
|
+
payload['servicePlanOptions'] = plan_opts
|
|
971
|
+
end
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
# prompt for network interfaces (if supported)
|
|
975
|
+
# Does not apply during BareMetal server imports
|
|
976
|
+
if !is_baremetal_host && server_type["provisionType"] && server_type["provisionType"]["id"] && server_type["provisionType"]["hasNetworks"]
|
|
977
|
+
begin
|
|
978
|
+
network_interfaces = prompt_network_interfaces(cloud['id'], server_type["provisionType"]["id"], pool_id, options)
|
|
979
|
+
if !network_interfaces.empty?
|
|
980
|
+
payload['networkInterfaces'] = network_interfaces
|
|
981
|
+
end
|
|
982
|
+
rescue RestClient::Exception => e
|
|
983
|
+
print yellow,"Unable to load network options. Proceeding...",reset,"\n"
|
|
984
|
+
print_rest_exception(e, options) if MtnCloud::Logging.debug?
|
|
985
|
+
end
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
# Security Groups
|
|
989
|
+
# prompt for multiple security groups
|
|
990
|
+
sg_option_type = option_type_list.find {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
|
|
991
|
+
option_type_list = option_type_list.reject {|opt| ((opt['code'] == 'provisionType.amazon.securityId') || (opt['name'] == 'securityId')) }
|
|
992
|
+
# ok.. seed data has changed and serverTypes do not have this optionType anymore...
|
|
993
|
+
if sg_option_type.nil?
|
|
994
|
+
if server_type["provisionType"] && (server_type["provisionType"]["code"] == 'amazon')
|
|
995
|
+
sg_option_type = {'fieldContext' => 'config', 'fieldName' => 'securityId', 'type' => 'select', 'fieldLabel' => 'Security Group', 'optionSource' => 'amazonSecurityGroup', 'required' => true, 'description' => 'Select security group.'}
|
|
996
|
+
end
|
|
997
|
+
end
|
|
998
|
+
has_security_groups = !!sg_option_type
|
|
999
|
+
if options[:security_groups]
|
|
1000
|
+
payload['securityGroups'] = options[:security_groups].collect {|sg_id| {'id' => sg_id} }
|
|
1001
|
+
else
|
|
1002
|
+
if has_security_groups
|
|
1003
|
+
security_groups_array = prompt_security_groups(sg_option_type, {zoneId: cloud_id, poolId: pool_id}, options)
|
|
1004
|
+
if !security_groups_array.empty?
|
|
1005
|
+
payload['securityGroups'] = security_groups_array.collect {|sg_id| {'id' => sg_id} }
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
metadata_option_type = option_type_list.find {|type| type['fieldName'] == 'metadata' }
|
|
1011
|
+
|
|
1012
|
+
# Metadata Tags
|
|
1013
|
+
if metadata_option_type
|
|
1014
|
+
if options[:metadata]
|
|
1015
|
+
metadata = parse_metadata(options[:metadata])
|
|
1016
|
+
payload['tags'] = metadata if !metadata.empty?
|
|
1017
|
+
else
|
|
1018
|
+
metadata = prompt_metadata(options)
|
|
1019
|
+
payload['tags'] = metadata if !metadata.empty?
|
|
1020
|
+
end
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
api_params = {}
|
|
1024
|
+
api_params['zoneId'] = cloud['id']
|
|
1025
|
+
api_params['poolId'] = payload['config']['resourcePool'] if (payload['config'] && payload['config']['resourcePool'])
|
|
1026
|
+
if payload['config']
|
|
1027
|
+
api_params.deep_merge!(payload['config'])
|
|
1028
|
+
end
|
|
1029
|
+
#api_params.deep_merge(payload)
|
|
1030
|
+
params = MtnCloud::Cli::OptionTypes.prompt(option_type_list,options[:options],@api_client, api_params)
|
|
1031
|
+
params.booleanize!
|
|
1032
|
+
payload.deep_merge!(params)
|
|
1033
|
+
|
|
1034
|
+
end
|
|
1035
|
+
@servers_interface.setopts(options)
|
|
1036
|
+
if options[:dry_run]
|
|
1037
|
+
print_dry_run @servers_interface.dry.create(payload)
|
|
1038
|
+
return
|
|
1039
|
+
end
|
|
1040
|
+
json_response = @servers_interface.create(payload)
|
|
1041
|
+
if options[:json]
|
|
1042
|
+
print JSON.pretty_generate(json_response)
|
|
1043
|
+
print "\n"
|
|
1044
|
+
elsif !options[:quiet]
|
|
1045
|
+
server_id = json_response["server"]["id"]
|
|
1046
|
+
server_name = json_response["server"]["name"]
|
|
1047
|
+
print_green_success "Provisioning host [#{server_id}] #{server_name}"
|
|
1048
|
+
# print details
|
|
1049
|
+
get_args = [server_id] + (options[:remote] ? ["-r",options[:remote]] : []) + (options[:refresh_interval] ? ['--refresh', options[:refresh_interval].to_s] : [])
|
|
1050
|
+
get(get_args)
|
|
1051
|
+
end
|
|
1052
|
+
rescue RestClient::Exception => e
|
|
1053
|
+
print_rest_exception(e, options)
|
|
1054
|
+
exit 1
|
|
1055
|
+
end
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
def update(args)
|
|
1059
|
+
options = {}
|
|
1060
|
+
params = {}
|
|
1061
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1062
|
+
opts.banner = subcommand_usage("[name]")
|
|
1063
|
+
opts.on('--name VALUE', String, "Name") do |val|
|
|
1064
|
+
params['name'] = val == "null" ? nil : val
|
|
1065
|
+
end
|
|
1066
|
+
opts.on('--description VALUE', String, "Description") do |val|
|
|
1067
|
+
params['description'] = val == "null" ? nil : val
|
|
1068
|
+
end
|
|
1069
|
+
opts.on('--ssh-username VALUE', String, "SSH Username") do |val|
|
|
1070
|
+
params['sshUsername'] = val == "null" ? nil : val
|
|
1071
|
+
end
|
|
1072
|
+
opts.on('--ssh-password VALUE', String, "SSH Password") do |val|
|
|
1073
|
+
params['sshPassword'] = val == "null" ? nil : val
|
|
1074
|
+
end
|
|
1075
|
+
opts.on('--ssh-key-pair ID', String, "SSH Key Pair ID") do |val|
|
|
1076
|
+
params['sshKeyPair'] = val == "null" ? nil : {"id" => val.to_i}
|
|
1077
|
+
end
|
|
1078
|
+
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
|
1079
|
+
params['powerScheduleType'] = val == "null" ? nil : val
|
|
1080
|
+
end
|
|
1081
|
+
opts.on('-l', '--labels [LIST]', String, "Labels") do |val|
|
|
1082
|
+
params['labels'] = parse_labels(val)
|
|
1083
|
+
end
|
|
1084
|
+
opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
|
|
1085
|
+
options[:tags] = val
|
|
1086
|
+
end
|
|
1087
|
+
opts.on('--metadata LIST', String, "Alias for --tags.") do |val|
|
|
1088
|
+
options[:tags] = val
|
|
1089
|
+
end
|
|
1090
|
+
opts.add_hidden_option('--metadata')
|
|
1091
|
+
opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
|
|
1092
|
+
options[:add_tags] = val
|
|
1093
|
+
end
|
|
1094
|
+
opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
|
|
1095
|
+
options[:remove_tags] = val
|
|
1096
|
+
end
|
|
1097
|
+
# opts.on('--created-by ID', String, "Created By User ID") do |val|
|
|
1098
|
+
# params['createdById'] = val
|
|
1099
|
+
# end
|
|
1100
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
|
1101
|
+
end
|
|
1102
|
+
optparse.parse!(args)
|
|
1103
|
+
if args.count != 1
|
|
1104
|
+
puts optparse
|
|
1105
|
+
return 1
|
|
1106
|
+
end
|
|
1107
|
+
connect(options)
|
|
1108
|
+
|
|
1109
|
+
begin
|
|
1110
|
+
server = find_host_by_name_or_id(args[0])
|
|
1111
|
+
return 1 if server.nil?
|
|
1112
|
+
new_group = nil
|
|
1113
|
+
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
1114
|
+
params.deep_merge!(passed_options) unless passed_options.empty?
|
|
1115
|
+
params.booleanize!
|
|
1116
|
+
# metadata tags
|
|
1117
|
+
if options[:tags]
|
|
1118
|
+
params['tags'] = parse_metadata(options[:tags])
|
|
1119
|
+
else
|
|
1120
|
+
# params['tags'] = prompt_metadata(options)
|
|
1121
|
+
end
|
|
1122
|
+
if options[:add_tags]
|
|
1123
|
+
params['addTags'] = parse_metadata(options[:add_tags])
|
|
1124
|
+
end
|
|
1125
|
+
if options[:remove_tags]
|
|
1126
|
+
params['removeTags'] = parse_metadata(options[:remove_tags])
|
|
1127
|
+
end
|
|
1128
|
+
payload = nil
|
|
1129
|
+
if options[:payload]
|
|
1130
|
+
payload = options[:payload]
|
|
1131
|
+
# support args and option parameters on top of payload
|
|
1132
|
+
if !params.empty?
|
|
1133
|
+
payload['server'] ||= {}
|
|
1134
|
+
payload['server'].deep_merge!(params)
|
|
1135
|
+
end
|
|
1136
|
+
else
|
|
1137
|
+
if params.empty?
|
|
1138
|
+
print_red_alert "Specify at least one option to update"
|
|
1139
|
+
puts optparse
|
|
1140
|
+
return 1
|
|
1141
|
+
end
|
|
1142
|
+
payload = {}
|
|
1143
|
+
payload['server'] = params
|
|
1144
|
+
end
|
|
1145
|
+
|
|
1146
|
+
@servers_interface.setopts(options)
|
|
1147
|
+
if options[:dry_run]
|
|
1148
|
+
print_dry_run @servers_interface.dry.update(server["id"], payload)
|
|
1149
|
+
return
|
|
1150
|
+
end
|
|
1151
|
+
json_response = @servers_interface.update(server["id"], payload)
|
|
1152
|
+
|
|
1153
|
+
if options[:json]
|
|
1154
|
+
puts as_json(json_response, options)
|
|
1155
|
+
else
|
|
1156
|
+
print_green_success "Updated host #{server['name']}"
|
|
1157
|
+
get([server['id']])
|
|
1158
|
+
end
|
|
1159
|
+
return 0
|
|
1160
|
+
rescue RestClient::Exception => e
|
|
1161
|
+
print_rest_exception(e, options)
|
|
1162
|
+
exit 1
|
|
1163
|
+
end
|
|
1164
|
+
end
|
|
1165
|
+
|
|
1166
|
+
def remove(args)
|
|
1167
|
+
options = {}
|
|
1168
|
+
query_params = {}
|
|
1169
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1170
|
+
opts.banner = subcommand_usage("[name]")
|
|
1171
|
+
# opts.on( '-S', '--skip-remove-infrastructure', "Skip removal of underlying cloud infrastructure. Same as --remove-resources off" ) do
|
|
1172
|
+
# query_params[:removeResources] = 'off'
|
|
1173
|
+
# end
|
|
1174
|
+
opts.on('--remove-resources [on|off]', ['on','off'], "Remove Infrastructure. Default is on if server is managed.") do |val|
|
|
1175
|
+
query_params[:removeResources] = val.nil? ? 'on' : val
|
|
1176
|
+
end
|
|
1177
|
+
opts.on('--preserve-volumes [on|off]', ['on','off'], "Preserve Volumes. Default is off.") do |val|
|
|
1178
|
+
query_params[:preserveVolumes] = val.nil? ? 'on' : val
|
|
1179
|
+
end
|
|
1180
|
+
opts.on('--remove-instances [on|off]', ['on','off'], "Remove Associated Instances. Default is off.") do |val|
|
|
1181
|
+
query_params[:removeInstances] = val.nil? ? 'on' : val
|
|
1182
|
+
end
|
|
1183
|
+
opts.on('--release-eips [on|off]', ['on','off'], "Release EIPs, default is on. Amazon only.") do |val|
|
|
1184
|
+
params[:releaseEIPs] = val.nil? ? 'on' : val
|
|
1185
|
+
end
|
|
1186
|
+
opts.on( '-f', '--force', "Force Delete" ) do
|
|
1187
|
+
query_params[:force] = 'on'
|
|
1188
|
+
end
|
|
1189
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
|
|
1190
|
+
end
|
|
1191
|
+
optparse.parse!(args)
|
|
1192
|
+
if args.count < 1
|
|
1193
|
+
puts optparse
|
|
1194
|
+
exit 1
|
|
1195
|
+
end
|
|
1196
|
+
connect(options)
|
|
1197
|
+
|
|
1198
|
+
begin
|
|
1199
|
+
server = find_host_by_name_or_id(args[0])
|
|
1200
|
+
unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to remove the server '#{server['name']}'?", options)
|
|
1201
|
+
exit 1
|
|
1202
|
+
end
|
|
1203
|
+
@servers_interface.setopts(options)
|
|
1204
|
+
if options[:dry_run]
|
|
1205
|
+
print_dry_run @servers_interface.dry.destroy(server['id'], query_params)
|
|
1206
|
+
return
|
|
1207
|
+
end
|
|
1208
|
+
json_response = @servers_interface.destroy(server['id'], query_params)
|
|
1209
|
+
if options[:json]
|
|
1210
|
+
print JSON.pretty_generate(json_response)
|
|
1211
|
+
print "\n"
|
|
1212
|
+
elsif !options[:quiet]
|
|
1213
|
+
if json_response['deleteApprovalRequired'] == true
|
|
1214
|
+
print_green_success "Delete Request created for Host #{server['name']}"
|
|
1215
|
+
else
|
|
1216
|
+
print_green_success "Host #{server['name']} is being removed..."
|
|
1217
|
+
end
|
|
1218
|
+
#list([])
|
|
1219
|
+
end
|
|
1220
|
+
rescue RestClient::Exception => e
|
|
1221
|
+
print_rest_exception(e, options)
|
|
1222
|
+
exit 1
|
|
1223
|
+
end
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
def start(args)
|
|
1227
|
+
options = {}
|
|
1228
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1229
|
+
opts.banner = subcommand_usage("[name]")
|
|
1230
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
|
1231
|
+
opts.footer = "Start a host.\n" +
|
|
1232
|
+
"[name] is required. This is the name or id of a host. Supports 1-N [name] arguments."
|
|
1233
|
+
end
|
|
1234
|
+
optparse.parse!(args)
|
|
1235
|
+
if args.count < 1
|
|
1236
|
+
puts optparse
|
|
1237
|
+
exit 1
|
|
1238
|
+
end
|
|
1239
|
+
connect(options)
|
|
1240
|
+
begin
|
|
1241
|
+
host_ids = parse_id_list(args)
|
|
1242
|
+
hosts = []
|
|
1243
|
+
host_ids.each do |host_id|
|
|
1244
|
+
host = find_host_by_name_or_id(host_id)
|
|
1245
|
+
return 1 if host.nil?
|
|
1246
|
+
hosts << host
|
|
1247
|
+
end
|
|
1248
|
+
objects_label = "#{hosts.size == 1 ? 'host' : (hosts.size.to_s + ' hosts')} #{anded_list(hosts.collect {|it| it['name'] })}"
|
|
1249
|
+
unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to start #{objects_label}?", options)
|
|
1250
|
+
return 9, "aborted command"
|
|
1251
|
+
end
|
|
1252
|
+
@servers_interface.setopts(options)
|
|
1253
|
+
if options[:dry_run]
|
|
1254
|
+
print_dry_run @servers_interface.dry.start(hosts.collect {|it| it['id'] })
|
|
1255
|
+
return
|
|
1256
|
+
end
|
|
1257
|
+
json_response = @servers_interface.start(hosts.collect {|it| it['id'] })
|
|
1258
|
+
if options[:json]
|
|
1259
|
+
print JSON.pretty_generate(json_response)
|
|
1260
|
+
print "\n"
|
|
1261
|
+
elsif !options[:quiet]
|
|
1262
|
+
print_green_success "Started #{objects_label}"
|
|
1263
|
+
end
|
|
1264
|
+
return 0
|
|
1265
|
+
rescue RestClient::Exception => e
|
|
1266
|
+
print_rest_exception(e, options)
|
|
1267
|
+
exit 1
|
|
1268
|
+
end
|
|
1269
|
+
end
|
|
1270
|
+
|
|
1271
|
+
def stop(args)
|
|
1272
|
+
options = {}
|
|
1273
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1274
|
+
opts.banner = subcommand_usage("[name]")
|
|
1275
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
|
1276
|
+
opts.footer = "Stop a host.\n" +
|
|
1277
|
+
"[name] is required. This is the name or id of a host. Supports 1-N [name] arguments."
|
|
1278
|
+
end
|
|
1279
|
+
optparse.parse!(args)
|
|
1280
|
+
if args.count < 1
|
|
1281
|
+
puts optparse
|
|
1282
|
+
exit 1
|
|
1283
|
+
end
|
|
1284
|
+
connect(options)
|
|
1285
|
+
begin
|
|
1286
|
+
host_ids = parse_id_list(args)
|
|
1287
|
+
hosts = []
|
|
1288
|
+
host_ids.each do |host_id|
|
|
1289
|
+
host = find_host_by_name_or_id(host_id)
|
|
1290
|
+
return 1 if host.nil?
|
|
1291
|
+
hosts << host
|
|
1292
|
+
end
|
|
1293
|
+
objects_label = "#{hosts.size == 1 ? 'host' : (hosts.size.to_s + ' hosts')} #{anded_list(hosts.collect {|it| it['name'] })}"
|
|
1294
|
+
unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to stop #{objects_label}?", options)
|
|
1295
|
+
return 9, "aborted command"
|
|
1296
|
+
end
|
|
1297
|
+
@servers_interface.setopts(options)
|
|
1298
|
+
if options[:dry_run]
|
|
1299
|
+
print_dry_run @servers_interface.dry.stop(hosts.collect {|it| it['id'] })
|
|
1300
|
+
return
|
|
1301
|
+
end
|
|
1302
|
+
json_response = @servers_interface.stop(hosts.collect {|it| it['id'] })
|
|
1303
|
+
if options[:json]
|
|
1304
|
+
print JSON.pretty_generate(json_response)
|
|
1305
|
+
print "\n"
|
|
1306
|
+
elsif !options[:quiet]
|
|
1307
|
+
print_green_success "Stopped #{objects_label}"
|
|
1308
|
+
end
|
|
1309
|
+
return 0
|
|
1310
|
+
rescue RestClient::Exception => e
|
|
1311
|
+
print_rest_exception(e, options)
|
|
1312
|
+
exit 1
|
|
1313
|
+
end
|
|
1314
|
+
end
|
|
1315
|
+
|
|
1316
|
+
def restart(args)
|
|
1317
|
+
options = {}
|
|
1318
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1319
|
+
opts.banner = subcommand_usage("[name]")
|
|
1320
|
+
build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
|
|
1321
|
+
opts.footer = "Restart a host.\n" +
|
|
1322
|
+
"[name] is required. This is the name or id of a host."
|
|
1323
|
+
end
|
|
1324
|
+
optparse.parse!(args)
|
|
1325
|
+
if args.count < 1
|
|
1326
|
+
puts optparse
|
|
1327
|
+
exit 1
|
|
1328
|
+
end
|
|
1329
|
+
connect(options)
|
|
1330
|
+
begin
|
|
1331
|
+
server = find_host_by_name_or_id(args[0])
|
|
1332
|
+
unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to restart the server '#{server['name']}'?", options)
|
|
1333
|
+
exit 1
|
|
1334
|
+
end
|
|
1335
|
+
@servers_interface.setopts(options)
|
|
1336
|
+
if options[:dry_run]
|
|
1337
|
+
print_dry_run @servers_interface.dry.restart(server['id'])
|
|
1338
|
+
return
|
|
1339
|
+
end
|
|
1340
|
+
json_response = @servers_interface.restart(server['id'])
|
|
1341
|
+
if options[:json]
|
|
1342
|
+
print JSON.pretty_generate(json_response)
|
|
1343
|
+
print "\n"
|
|
1344
|
+
elsif !options[:quiet]
|
|
1345
|
+
print_green_success "Restarting #{server["name"]}"
|
|
1346
|
+
end
|
|
1347
|
+
rescue RestClient::Exception => e
|
|
1348
|
+
print_rest_exception(e, options)
|
|
1349
|
+
exit 1
|
|
1350
|
+
end
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
def resize(args)
|
|
1355
|
+
options = {}
|
|
1356
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1357
|
+
opts.banner = subcommand_usage("[name]")
|
|
1358
|
+
opts.on("--storage-controller ARRAY", String, "Storage Controllers, JSON array of controller configs. Each entry accepts id, busNumber, typeId, typeName, removable, editable.") do |val|
|
|
1359
|
+
options[:options] ||= {}
|
|
1360
|
+
options[:options]['storageController'] = JSON.parse(val)
|
|
1361
|
+
end
|
|
1362
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
|
|
1363
|
+
end
|
|
1364
|
+
optparse.parse!(args)
|
|
1365
|
+
if args.count < 1
|
|
1366
|
+
puts optparse
|
|
1367
|
+
exit 1
|
|
1368
|
+
end
|
|
1369
|
+
connect(options)
|
|
1370
|
+
begin
|
|
1371
|
+
server = find_host_by_name_or_id(args[0])
|
|
1372
|
+
|
|
1373
|
+
group_id = server["siteId"] || erver['group']['id']
|
|
1374
|
+
cloud_id = server["zoneId"] || server["zone"]["id"]
|
|
1375
|
+
server_type_id = server['computeServerType']['id']
|
|
1376
|
+
plan_id = server['plan']['id']
|
|
1377
|
+
payload = {
|
|
1378
|
+
:server => {:id => server["id"]}
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
# need to GET provision type for some settings...
|
|
1382
|
+
server_type = @server_types_interface.get(server_type_id)['serverType']
|
|
1383
|
+
provision_type = @provision_types_interface.get(server_type['provisionType']['id'])['provisionType']
|
|
1384
|
+
|
|
1385
|
+
# avoid 500 error
|
|
1386
|
+
# payload[:servicePlanOptions] = {}
|
|
1387
|
+
unless options[:no_prompt]
|
|
1388
|
+
puts "\nDue to limitations by most Guest Operating Systems, Disk sizes can only be expanded and not reduced.\nIf a smaller plan is selected, memory and CPU (if relevant) will be reduced but storage will not.\n\n"
|
|
1389
|
+
# unless hot_resize
|
|
1390
|
+
# puts "\nWARNING: Resize actions for this server will cause instances to be restarted.\n\n"
|
|
1391
|
+
# end
|
|
1392
|
+
end
|
|
1393
|
+
|
|
1394
|
+
# prompt for service plan
|
|
1395
|
+
service_plans_json = @servers_interface.service_plans({zoneId: cloud_id, serverTypeId: server_type_id, serverId: server['id']})
|
|
1396
|
+
service_plans = service_plans_json["plans"]
|
|
1397
|
+
service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
|
|
1398
|
+
service_plans_dropdown.each do |plan|
|
|
1399
|
+
if plan['value'] && plan['value'].to_i == plan_id.to_i
|
|
1400
|
+
plan['name'] = "#{plan['name']} (current)"
|
|
1401
|
+
end
|
|
1402
|
+
end
|
|
1403
|
+
plan_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'plan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'defaultValue' => plan_id, 'description' => 'Choose the appropriately sized plan for this server'}],options[:options])
|
|
1404
|
+
service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['plan'].to_i }
|
|
1405
|
+
payload[:server][:plan] = {id: service_plan["id"]}
|
|
1406
|
+
|
|
1407
|
+
# fetch volumes
|
|
1408
|
+
current_volumes = nil
|
|
1409
|
+
if server['volumes']
|
|
1410
|
+
current_volumes = server['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
|
|
1411
|
+
else
|
|
1412
|
+
volumes_response = @servers_interface.volumes(server['id'])
|
|
1413
|
+
current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
|
|
1414
|
+
end
|
|
1415
|
+
|
|
1416
|
+
# prompt for volumes
|
|
1417
|
+
vol_options = options
|
|
1418
|
+
vol_options['siteId'] = group_id
|
|
1419
|
+
vol_options['zoneId'] = cloud_id
|
|
1420
|
+
vol_options['resourcePoolId'] = server['resourcePool']['id'] if server['resourcePool']
|
|
1421
|
+
volumes = prompt_resize_volumes(current_volumes, service_plan, provision_type, vol_options, server)
|
|
1422
|
+
if !volumes.empty?
|
|
1423
|
+
payload[:volumes] = volumes
|
|
1424
|
+
end
|
|
1425
|
+
|
|
1426
|
+
# plan customizations
|
|
1427
|
+
plan_opts = prompt_service_plan_options(service_plan, options, @api_client, {}, server)
|
|
1428
|
+
if plan_opts && !plan_opts.empty?
|
|
1429
|
+
payload['servicePlanOptions'] = plan_opts
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
# todo: reconfigure networks
|
|
1433
|
+
# need to get provision_type_id for network info
|
|
1434
|
+
# prompt for network interfaces (if supported)
|
|
1435
|
+
# if server_type["provisionType"] && server_type["provisionType"]["id"] && server_type["provisionType"]["hasNetworks"]
|
|
1436
|
+
# begin
|
|
1437
|
+
# network_interfaces = prompt_network_interfaces(cloud['id'], server_type["provisionType"]["id"], null, options)
|
|
1438
|
+
# if !network_interfaces.empty?
|
|
1439
|
+
# payload[:networkInterfaces] = network_interfaces
|
|
1440
|
+
# end
|
|
1441
|
+
# rescue RestClient::Exception => e
|
|
1442
|
+
# print yellow,"Unable to load network options. Proceeding...",reset,"\n"
|
|
1443
|
+
# print_rest_exception(e, options) if MtnCloud::Logging.debug?
|
|
1444
|
+
# end
|
|
1445
|
+
# end
|
|
1446
|
+
|
|
1447
|
+
# only amazon supports this option
|
|
1448
|
+
# for now, always do this
|
|
1449
|
+
payload[:deleteOriginalVolumes] = true
|
|
1450
|
+
if options[:options] && options[:options]['storageController']
|
|
1451
|
+
payload[:storageController] = options[:options]['storageController']
|
|
1452
|
+
end
|
|
1453
|
+
@servers_interface.setopts(options)
|
|
1454
|
+
if options[:dry_run]
|
|
1455
|
+
print_dry_run @servers_interface.dry.resize(server['id'], payload)
|
|
1456
|
+
return
|
|
1457
|
+
end
|
|
1458
|
+
json_response = @servers_interface.resize(server['id'], payload)
|
|
1459
|
+
if options[:json]
|
|
1460
|
+
print JSON.pretty_generate(json_response)
|
|
1461
|
+
print "\n"
|
|
1462
|
+
else
|
|
1463
|
+
unless options[:quiet]
|
|
1464
|
+
puts "Host #{server['name']} resizing..."
|
|
1465
|
+
list([])
|
|
1466
|
+
end
|
|
1467
|
+
end
|
|
1468
|
+
rescue RestClient::Exception => e
|
|
1469
|
+
print_rest_exception(e, options)
|
|
1470
|
+
exit 1
|
|
1471
|
+
end
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
# Prompt for instance version and layout based on instance type.
|
|
1475
|
+
def prompt_make_managed_instance_options(instance_type, group_id, cloud_id, options={})
|
|
1476
|
+
opt_bucket = options[:options] || {}
|
|
1477
|
+
|
|
1478
|
+
# available versions for this instance type
|
|
1479
|
+
version_source_params = {groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id']}
|
|
1480
|
+
available_versions = options_interface.options_for_source('instanceVersions', version_source_params)['data'] || []
|
|
1481
|
+
# filter out versions that have no layouts
|
|
1482
|
+
available_versions.reject! { |ver| ver['layouts'].nil? || ver['layouts'].empty? }
|
|
1483
|
+
available_versions.sort! { |x,y| x['name']<=> y['name'] }
|
|
1484
|
+
|
|
1485
|
+
# validate version option
|
|
1486
|
+
if opt_bucket['version']
|
|
1487
|
+
selected_version = opt_bucket['version']
|
|
1488
|
+
unless available_versions.find {|av| av['name'].to_s == selected_version.to_s }
|
|
1489
|
+
raise_command_error "Invalid version option '#{selected_version}' passed. Valid versions are: #{available_versions.collect {|av| av['name']}.join(', ')}"
|
|
1490
|
+
end
|
|
1491
|
+
end
|
|
1492
|
+
# prompt for version
|
|
1493
|
+
version_prompt = MtnCloud::Cli::OptionTypes.prompt([{
|
|
1494
|
+
'fieldName' => 'version',
|
|
1495
|
+
'type' => 'select',
|
|
1496
|
+
'fieldLabel' => 'Version',
|
|
1497
|
+
'selectOptions' => available_versions,
|
|
1498
|
+
'required' => true,
|
|
1499
|
+
'defaultValue' => available_versions.first ? available_versions.first['value'] : '',
|
|
1500
|
+
'description' => 'Instance Type Version'
|
|
1501
|
+
}],
|
|
1502
|
+
opt_bucket
|
|
1503
|
+
)
|
|
1504
|
+
selected_version_value = version_prompt['version']
|
|
1505
|
+
|
|
1506
|
+
# filter layouts that support the selected version and are unmanaged or support convert to managed
|
|
1507
|
+
layouts_for_version = (instance_type['instanceTypeLayouts'] || []).select { |layout|
|
|
1508
|
+
(layout['instanceVersion'] == selected_version_value) &&
|
|
1509
|
+
(layout['supportsConvertToManaged'] == true || layout['serverType'] == 'unmanaged')
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
if layouts_for_version.empty?
|
|
1513
|
+
print_red_alert "No available layouts that support converting to managed for the given instance type"
|
|
1514
|
+
return nil
|
|
1515
|
+
end
|
|
1516
|
+
|
|
1517
|
+
layout_options = layouts_for_version.collect { |layout|
|
|
1518
|
+
{'name' => layout['name'], 'value' => layout['id']}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
# validate layout input option
|
|
1522
|
+
if opt_bucket['layout']
|
|
1523
|
+
default_layout = opt_bucket['layout']
|
|
1524
|
+
unless layout_options.find {|lo| lo['name'].to_s == default_layout.to_s }
|
|
1525
|
+
raise_command_error "Invalid layout option '#{default_layout}' passed. Valid layouts are: #{layout_options.collect {|lo| lo['name']}.join(', ')}"
|
|
1526
|
+
end
|
|
1527
|
+
end
|
|
1528
|
+
|
|
1529
|
+
layout_prompt = MtnCloud::Cli::OptionTypes.prompt(
|
|
1530
|
+
[{
|
|
1531
|
+
'fieldName' => 'layout',
|
|
1532
|
+
'type' => 'select',
|
|
1533
|
+
'fieldLabel' => 'Layout',
|
|
1534
|
+
'selectOptions' => layout_options,
|
|
1535
|
+
'required' => true,
|
|
1536
|
+
'defaultValue' => layout_options.first ? layout_options.first['value'] : '',
|
|
1537
|
+
'description' => 'Choose a layout (template) for this instance.'
|
|
1538
|
+
}],
|
|
1539
|
+
opt_bucket
|
|
1540
|
+
)
|
|
1541
|
+
chosen_layout_id = layout_prompt['layout']
|
|
1542
|
+
|
|
1543
|
+
{'instanceVersion' => selected_version_value, 'instanceLayoutId' => chosen_layout_id}
|
|
1544
|
+
end
|
|
1545
|
+
private :prompt_make_managed_instance_options
|
|
1546
|
+
|
|
1547
|
+
def make_managed(args)
|
|
1548
|
+
options = {}
|
|
1549
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1550
|
+
opts.banner = subcommand_usage("[name]")
|
|
1551
|
+
build_option_type_options(opts, options, make_managed_option_types(false))
|
|
1552
|
+
opts.on('--install-agent [on|off]', String, "Install Agent? Pass false to manually install agent. Default is true.") do |val|
|
|
1553
|
+
options['installAgent'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
|
|
1554
|
+
end
|
|
1555
|
+
opts.on('-g', '--group GROUP', String, "Group to assign to new instance.") do |val|
|
|
1556
|
+
options[:group] = val
|
|
1557
|
+
end
|
|
1558
|
+
opts.on('--instance-type ID', String, "Instance Type ID or Name for the new instance. Optional - only specify if you want to set a specific instance type for conversion.") do |val|
|
|
1559
|
+
options['instanceType'] = val
|
|
1560
|
+
end
|
|
1561
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
|
|
1562
|
+
end
|
|
1563
|
+
optparse.parse!(args)
|
|
1564
|
+
if args.count < 1
|
|
1565
|
+
puts optparse
|
|
1566
|
+
exit 1
|
|
1567
|
+
end
|
|
1568
|
+
connect(options)
|
|
1569
|
+
begin
|
|
1570
|
+
host = find_host_by_name_or_id(args[0])
|
|
1571
|
+
if host['agentInstalled']
|
|
1572
|
+
print_red_alert "Agent already installed on host '#{host['name']}'"
|
|
1573
|
+
return false
|
|
1574
|
+
end
|
|
1575
|
+
payload = {
|
|
1576
|
+
'server' => {}
|
|
1577
|
+
}
|
|
1578
|
+
passed_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) }
|
|
1579
|
+
payload.deep_merge!(passed_options)
|
|
1580
|
+
params = MtnCloud::Cli::OptionTypes.prompt(make_managed_option_types, options[:options], @api_client, options[:params])
|
|
1581
|
+
server_os = params.delete('serverOs')
|
|
1582
|
+
if server_os
|
|
1583
|
+
payload['server']['serverOs'] = {id: server_os}
|
|
1584
|
+
end
|
|
1585
|
+
account_id = params.delete('account') # not yet implemented
|
|
1586
|
+
if account_id
|
|
1587
|
+
payload['server']['account'] = {id: account}
|
|
1588
|
+
end
|
|
1589
|
+
if options[:group]
|
|
1590
|
+
group = options[:group] ? find_group_by_name_or_id_for_provisioning(options[:group]) : nil
|
|
1591
|
+
return 1 if group.nil?
|
|
1592
|
+
params['provisionSiteId'] = group['id']
|
|
1593
|
+
end
|
|
1594
|
+
payload['server'].merge!(params)
|
|
1595
|
+
['installAgent'].each do |k|
|
|
1596
|
+
if options[k] != nil
|
|
1597
|
+
payload[k] = options[k]
|
|
1598
|
+
end
|
|
1599
|
+
end
|
|
1600
|
+
# If instance type is passed, prompt for version and layout
|
|
1601
|
+
unless options['instanceType'].nil?
|
|
1602
|
+
instance_type = find_instance_type_by_name_or_id(options['instanceType'])
|
|
1603
|
+
if instance_type.nil?
|
|
1604
|
+
print_red_alert "Instance Type not found by name or id #{options['instanceType']}"
|
|
1605
|
+
return 1
|
|
1606
|
+
end
|
|
1607
|
+
if instance_type['active'] != true
|
|
1608
|
+
print_red_alert "Instance Type '#{options['instanceType']}' (#{instance_type['name']}) is not active"
|
|
1609
|
+
return 1
|
|
1610
|
+
end
|
|
1611
|
+
resp=prompt_make_managed_instance_options(instance_type, params['provisionSiteId'] || host['siteId'],
|
|
1612
|
+
(host['zoneId'] || host['zone']['id']), options)
|
|
1613
|
+
if resp.nil?
|
|
1614
|
+
print_red_alert "Failed to select instance version and layout for given instance type '#{instance_type['name']}'"
|
|
1615
|
+
return 1
|
|
1616
|
+
end
|
|
1617
|
+
payload['instanceTypeId'] = instance_type['id']
|
|
1618
|
+
payload['layout'] = resp['instanceLayoutId']
|
|
1619
|
+
payload['version'] = resp['instanceVersion']
|
|
1620
|
+
end
|
|
1621
|
+
|
|
1622
|
+
@servers_interface.setopts(options)
|
|
1623
|
+
if options[:dry_run]
|
|
1624
|
+
print_dry_run(@servers_interface.dry.make_managed(host['id'], payload), options)
|
|
1625
|
+
return 0
|
|
1626
|
+
end
|
|
1627
|
+
json_response = @servers_interface.make_managed(host['id'], payload)
|
|
1628
|
+
if options[:json]
|
|
1629
|
+
print JSON.pretty_generate(json_response)
|
|
1630
|
+
print "\n"
|
|
1631
|
+
elsif !options[:quiet]
|
|
1632
|
+
print_green_success "Host #{host['name']} is being converted to managed."
|
|
1633
|
+
puts "Public Key:\n#{json_response['publicKey']}\n(copy to your authorized_keys file)"
|
|
1634
|
+
end
|
|
1635
|
+
return 0
|
|
1636
|
+
rescue RestClient::Exception => e
|
|
1637
|
+
print_rest_exception(e, options)
|
|
1638
|
+
exit 1
|
|
1639
|
+
end
|
|
1640
|
+
end
|
|
1641
|
+
|
|
1642
|
+
def upgrade_agent(args)
|
|
1643
|
+
options = {}
|
|
1644
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1645
|
+
opts.banner = subcommand_usage("[host]")
|
|
1646
|
+
opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
|
|
1647
|
+
options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
|
|
1648
|
+
end
|
|
1649
|
+
opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
|
1650
|
+
options[:no_refresh] = true
|
|
1651
|
+
end
|
|
1652
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
1653
|
+
opts.footer = <<-EOT
|
|
1654
|
+
Upgrade agent for a host.
|
|
1655
|
+
[host] is required. This is the name or id of a host.
|
|
1656
|
+
EOT
|
|
1657
|
+
end
|
|
1658
|
+
optparse.parse!(args)
|
|
1659
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
1660
|
+
connect(options)
|
|
1661
|
+
|
|
1662
|
+
host = find_host_by_name_or_id(args[0])
|
|
1663
|
+
return 1 if host.nil?
|
|
1664
|
+
|
|
1665
|
+
payload = {}
|
|
1666
|
+
if options[:payload]
|
|
1667
|
+
payload = options[:payload]
|
|
1668
|
+
payload.deep_merge!({'server' => parse_passed_options(options)})
|
|
1669
|
+
else
|
|
1670
|
+
payload.deep_merge!({'server' => parse_passed_options(options)})
|
|
1671
|
+
end
|
|
1672
|
+
|
|
1673
|
+
@servers_interface.setopts(options)
|
|
1674
|
+
if options[:dry_run]
|
|
1675
|
+
print_dry_run @servers_interface.dry.upgrade(host['id'], payload)
|
|
1676
|
+
return
|
|
1677
|
+
end
|
|
1678
|
+
json_response = @servers_interface.upgrade(host['id'], payload)
|
|
1679
|
+
render_response(json_response, options) do
|
|
1680
|
+
#get([host['id']])
|
|
1681
|
+
if json_response['success']
|
|
1682
|
+
if json_response['msg'] == nil
|
|
1683
|
+
print_green_success "Upgrading agent on host #{host['name']}..."
|
|
1684
|
+
else
|
|
1685
|
+
print_green_success json_response['msg']
|
|
1686
|
+
end
|
|
1687
|
+
process_id = json_response['processId'] || (json_response['processIds'] ? json_response['processIds'][0] : nil)
|
|
1688
|
+
if process_id
|
|
1689
|
+
unless options[:no_refresh]
|
|
1690
|
+
process = wait_for_process_execution(process_id, options)
|
|
1691
|
+
end
|
|
1692
|
+
else
|
|
1693
|
+
# puts "No process returned"
|
|
1694
|
+
end
|
|
1695
|
+
else
|
|
1696
|
+
# never reached because unsuccessful requests raise an exception
|
|
1697
|
+
print_red_alert "API Request failed: #{json_response['msg']}"
|
|
1698
|
+
end
|
|
1699
|
+
end
|
|
1700
|
+
end
|
|
1701
|
+
|
|
1702
|
+
def run_workflow(args)
|
|
1703
|
+
params = {}
|
|
1704
|
+
options = {}
|
|
1705
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1706
|
+
opts.banner = subcommand_usage("[host] [workflow] [options]")
|
|
1707
|
+
opts.on("--phase PHASE", String, "Task Phase to run for Provisioning workflows. The default is provision.") do |val|
|
|
1708
|
+
options[:phase] = val
|
|
1709
|
+
end
|
|
1710
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
|
1711
|
+
opts.footer = <<-EOT
|
|
1712
|
+
Run workflow for a host.
|
|
1713
|
+
[host] is required. This is the name or id of a host
|
|
1714
|
+
[workflow] is required. This is the name or id of a workflow
|
|
1715
|
+
By default the provision phase is executed.
|
|
1716
|
+
Use the --phase option to execute a different phase.
|
|
1717
|
+
The available phases are start, stop, preProvision, provision, postProvision, preDeploy, deploy, reconfigure, teardown, startup and shutdown.
|
|
1718
|
+
EOT
|
|
1719
|
+
end
|
|
1720
|
+
optparse.parse!(args)
|
|
1721
|
+
if args.count != 2
|
|
1722
|
+
puts_error "#{MtnCloud::Terminal.angry_prompt}wrong number of arguments. Expected 2 and received #{args.count} #{args.inspect}\n#{optparse}"
|
|
1723
|
+
return 1
|
|
1724
|
+
end
|
|
1725
|
+
connect(options)
|
|
1726
|
+
|
|
1727
|
+
host = find_host_by_name_or_id(args[0])
|
|
1728
|
+
return 1 if host.nil?
|
|
1729
|
+
workflow = find_workflow_by_name_or_id(args[1])
|
|
1730
|
+
return 1 if workflow.nil?
|
|
1731
|
+
|
|
1732
|
+
# support -O options as arbitrary params
|
|
1733
|
+
old_option_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) }
|
|
1734
|
+
params.deep_merge!(old_option_options) unless old_option_options.empty?
|
|
1735
|
+
|
|
1736
|
+
# the payload format is unusual
|
|
1737
|
+
# payload example: {"taskSet": {taskSetId": {"taskSetTaskId": {"customOptions": {"dbVersion":"5.6"}}}}}
|
|
1738
|
+
payload = nil
|
|
1739
|
+
if options[:payload]
|
|
1740
|
+
payload = options[:payload]
|
|
1741
|
+
else
|
|
1742
|
+
payload = {}
|
|
1743
|
+
# i guess you must pass an option if there are editable options
|
|
1744
|
+
# any option, heh
|
|
1745
|
+
task_types = @tasks_interface.list_types()
|
|
1746
|
+
editable_options = []
|
|
1747
|
+
workflow['taskSetTasks'].sort{|a,b| a['taskOrder'] <=> b['taskOrder']}.each do |task_set_task|
|
|
1748
|
+
task_type_id = task_set_task['task']['taskType']['id']
|
|
1749
|
+
task_type = task_types['taskTypes'].find{ |current_task_type| current_task_type['id'] == task_type_id}
|
|
1750
|
+
task_opts = task_type['optionTypes'].select { |otype| otype['editable']}
|
|
1751
|
+
if !task_opts.nil? && !task_opts.empty?
|
|
1752
|
+
editable_options += task_opts.collect do |task_opt|
|
|
1753
|
+
new_task_opt = task_opt.clone
|
|
1754
|
+
new_task_opt['fieldContext'] = "#{task_set_task['id']}.#{new_task_opt['fieldContext']}"
|
|
1755
|
+
end
|
|
1756
|
+
end
|
|
1757
|
+
end
|
|
1758
|
+
# if params.empty? && !editable_options.empty?
|
|
1759
|
+
# puts optparse
|
|
1760
|
+
# option_lines = editable_options.collect {|it| "\t-O #{it['fieldContext'] ? (it['fieldContext'] + '.') : ''}#{it['fieldName']}=\"value\"" }.join("\n")
|
|
1761
|
+
# puts "\nAvailable Options:\n#{option_lines}\n\n"
|
|
1762
|
+
# return 1
|
|
1763
|
+
# end
|
|
1764
|
+
|
|
1765
|
+
end
|
|
1766
|
+
|
|
1767
|
+
if !params.empty?
|
|
1768
|
+
payload['taskSet'] ||= {}
|
|
1769
|
+
payload['taskSet']["#{workflow['id']}"] ||= {}
|
|
1770
|
+
payload['taskSet']["#{workflow['id']}"].deep_merge!(params)
|
|
1771
|
+
end
|
|
1772
|
+
if options[:phase]
|
|
1773
|
+
payload['taskPhase'] = options[:phase]
|
|
1774
|
+
end
|
|
1775
|
+
begin
|
|
1776
|
+
@servers_interface.setopts(options)
|
|
1777
|
+
if options[:dry_run]
|
|
1778
|
+
print_dry_run @servers_interface.dry.workflow(host['id'],workflow['id'], payload)
|
|
1779
|
+
return
|
|
1780
|
+
end
|
|
1781
|
+
json_response = @servers_interface.workflow(host['id'],workflow['id'], payload)
|
|
1782
|
+
if options[:json]
|
|
1783
|
+
print as_json(json_response, options), "\n"
|
|
1784
|
+
return
|
|
1785
|
+
elsif options[:quiet]
|
|
1786
|
+
return 0
|
|
1787
|
+
else
|
|
1788
|
+
print_green_success "Running workflow #{workflow['name']} on host #{host['name']} ..."
|
|
1789
|
+
end
|
|
1790
|
+
return 0
|
|
1791
|
+
rescue RestClient::Exception => e
|
|
1792
|
+
print_rest_exception(e, options)
|
|
1793
|
+
exit 1
|
|
1794
|
+
end
|
|
1795
|
+
end
|
|
1796
|
+
|
|
1797
|
+
def execution_request(args)
|
|
1798
|
+
options = {}
|
|
1799
|
+
params = {}
|
|
1800
|
+
script_content = nil
|
|
1801
|
+
do_refresh = true
|
|
1802
|
+
optparse = MtnCloud::Cli::OptionParser.new do|opts|
|
|
1803
|
+
opts.banner = subcommand_usage("[id] [options]")
|
|
1804
|
+
opts.on('--script SCRIPT', "Script to be executed" ) do |val|
|
|
1805
|
+
script_content = val
|
|
1806
|
+
end
|
|
1807
|
+
opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename|
|
|
1808
|
+
full_filename = File.expand_path(filename)
|
|
1809
|
+
if File.exist?(full_filename)
|
|
1810
|
+
script_content = File.read(full_filename)
|
|
1811
|
+
else
|
|
1812
|
+
print_red_alert "File not found: #{full_filename}"
|
|
1813
|
+
exit 1
|
|
1814
|
+
end
|
|
1815
|
+
end
|
|
1816
|
+
opts.on(nil, '--no-refresh', "Do not refresh until finished" ) do
|
|
1817
|
+
do_refresh = false
|
|
1818
|
+
end
|
|
1819
|
+
#build_option_type_options(opts, options, add_user_source_option_types())
|
|
1820
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
|
1821
|
+
opts.footer = "Execute an arbitrary command or script on a host." + "\n" +
|
|
1822
|
+
"[id] is required. This is the id a host." + "\n" +
|
|
1823
|
+
"[script] is required. This is the script that is to be executed."
|
|
1824
|
+
end
|
|
1825
|
+
optparse.parse!(args)
|
|
1826
|
+
connect(options)
|
|
1827
|
+
if args.count != 1
|
|
1828
|
+
print_error MtnCloud::Terminal.angry_prompt
|
|
1829
|
+
puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
|
|
1830
|
+
return 1
|
|
1831
|
+
end
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
begin
|
|
1835
|
+
host = find_host_by_name_or_id(args[0])
|
|
1836
|
+
return 1 if host.nil?
|
|
1837
|
+
params['serverId'] = host['id']
|
|
1838
|
+
# construct payload
|
|
1839
|
+
payload = {}
|
|
1840
|
+
if options[:payload]
|
|
1841
|
+
payload = options[:payload]
|
|
1842
|
+
else
|
|
1843
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
|
1844
|
+
# prompt for Script
|
|
1845
|
+
if script_content.nil?
|
|
1846
|
+
v_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'script', 'type' => 'code-editor', 'fieldLabel' => 'Script', 'required' => true, 'description' => 'The script content'}], options[:options])
|
|
1847
|
+
script_content = v_prompt['script']
|
|
1848
|
+
end
|
|
1849
|
+
payload['script'] = script_content
|
|
1850
|
+
end
|
|
1851
|
+
# dry run?
|
|
1852
|
+
@servers_interface.setopts(options)
|
|
1853
|
+
if options[:dry_run]
|
|
1854
|
+
print_dry_run @execution_request_interface.dry.create(params, payload)
|
|
1855
|
+
return 0
|
|
1856
|
+
end
|
|
1857
|
+
# do it
|
|
1858
|
+
json_response = @execution_request_interface.create(params, payload)
|
|
1859
|
+
# print and return result
|
|
1860
|
+
if options[:quiet]
|
|
1861
|
+
return 0
|
|
1862
|
+
elsif options[:json]
|
|
1863
|
+
puts as_json(json_response, options)
|
|
1864
|
+
return 0
|
|
1865
|
+
end
|
|
1866
|
+
execution_request = json_response['executionRequest']
|
|
1867
|
+
print_green_success "Executing request #{execution_request['uniqueId']}"
|
|
1868
|
+
if do_refresh
|
|
1869
|
+
MtnCloud::Cli::ExecutionRequestCommand.new.handle(["get", execution_request['uniqueId'], "--refresh"]+ (options[:remote] ? ["-r",options[:remote]] : []))
|
|
1870
|
+
else
|
|
1871
|
+
MtnCloud::Cli::ExecutionRequestCommand.new.handle(["get", execution_request['uniqueId']]+ (options[:remote] ? ["-r",options[:remote]] : []))
|
|
1872
|
+
end
|
|
1873
|
+
return 0
|
|
1874
|
+
rescue RestClient::Exception => e
|
|
1875
|
+
print_rest_exception(e, options)
|
|
1876
|
+
exit 1
|
|
1877
|
+
end
|
|
1878
|
+
end
|
|
1879
|
+
|
|
1880
|
+
def server_types_for_cloud(cloud_id, options)
|
|
1881
|
+
connect(options)
|
|
1882
|
+
zone = find_zone_by_name_or_id(nil, cloud_id)
|
|
1883
|
+
cloud_type = cloud_type_for_id(zone['zoneTypeId'])
|
|
1884
|
+
cloud_server_types = cloud_type['serverTypes'].select{|b| b['creatable'] == true}
|
|
1885
|
+
cloud_server_types = cloud_server_types.sort { |x,y| x['displayOrder'] <=> y['displayOrder'] }
|
|
1886
|
+
if options[:json]
|
|
1887
|
+
print JSON.pretty_generate(cloud_server_types)
|
|
1888
|
+
print "\n"
|
|
1889
|
+
else
|
|
1890
|
+
print_h1 "Server Types - Cloud: #{zone['name']}", [], options
|
|
1891
|
+
if cloud_server_types.nil? || cloud_server_types.empty?
|
|
1892
|
+
print cyan,"No server types found for the selected cloud",reset,"\n"
|
|
1893
|
+
else
|
|
1894
|
+
cloud_server_types.each do |server_type|
|
|
1895
|
+
print cyan, "[#{server_type['code']}]".ljust(20), " - ", "#{server_type['name']}", "\n"
|
|
1896
|
+
end
|
|
1897
|
+
end
|
|
1898
|
+
print reset,"\n"
|
|
1899
|
+
end
|
|
1900
|
+
end
|
|
1901
|
+
|
|
1902
|
+
def list_types(args)
|
|
1903
|
+
options = {}
|
|
1904
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1905
|
+
opts.banner = subcommand_usage()
|
|
1906
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
|
1907
|
+
options[:cloud] = val
|
|
1908
|
+
end
|
|
1909
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
|
1910
|
+
opts.footer = "List host types."
|
|
1911
|
+
end
|
|
1912
|
+
optparse.parse!(args)
|
|
1913
|
+
connect(options)
|
|
1914
|
+
begin
|
|
1915
|
+
params = {}
|
|
1916
|
+
params.merge!(parse_list_options(options))
|
|
1917
|
+
if options[:cloud]
|
|
1918
|
+
#return server_types_for_cloud(options[:cloud], options)
|
|
1919
|
+
zone = find_zone_by_name_or_id(nil, options[:cloud])
|
|
1920
|
+
params["zoneTypeId"] = zone['zoneTypeId']
|
|
1921
|
+
params["creatable"] = true
|
|
1922
|
+
end
|
|
1923
|
+
@server_types_interface.setopts(options)
|
|
1924
|
+
if options[:dry_run]
|
|
1925
|
+
print_dry_run @server_types_interface.dry.list(params)
|
|
1926
|
+
return
|
|
1927
|
+
end
|
|
1928
|
+
json_response = @server_types_interface.list(params)
|
|
1929
|
+
|
|
1930
|
+
render_result = render_with_format(json_response, options, 'serverTypes')
|
|
1931
|
+
return 0 if render_result
|
|
1932
|
+
|
|
1933
|
+
server_types = json_response['serverTypes']
|
|
1934
|
+
|
|
1935
|
+
title = "Server Types"
|
|
1936
|
+
subtitles = []
|
|
1937
|
+
subtitles += parse_list_subtitles(options)
|
|
1938
|
+
if options[:cloud]
|
|
1939
|
+
subtitles << "Cloud: #{options[:cloud]}"
|
|
1940
|
+
end
|
|
1941
|
+
print_h1 title, subtitles
|
|
1942
|
+
if server_types.empty?
|
|
1943
|
+
print cyan,"No server types found.",reset,"\n"
|
|
1944
|
+
else
|
|
1945
|
+
rows = server_types.collect do |server_type|
|
|
1946
|
+
{
|
|
1947
|
+
id: server_type['id'],
|
|
1948
|
+
code: server_type['code'],
|
|
1949
|
+
name: server_type['name']
|
|
1950
|
+
}
|
|
1951
|
+
end
|
|
1952
|
+
columns = [:id, :name, :code]
|
|
1953
|
+
print cyan
|
|
1954
|
+
print as_pretty_table(rows, columns, options)
|
|
1955
|
+
print reset
|
|
1956
|
+
print_results_pagination(json_response)
|
|
1957
|
+
end
|
|
1958
|
+
print reset,"\n"
|
|
1959
|
+
return 0
|
|
1960
|
+
|
|
1961
|
+
rescue RestClient::Exception => e
|
|
1962
|
+
print_rest_exception(e, options)
|
|
1963
|
+
exit 1
|
|
1964
|
+
end
|
|
1965
|
+
end
|
|
1966
|
+
|
|
1967
|
+
def view(args)
|
|
1968
|
+
options = {}
|
|
1969
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
1970
|
+
opts.banner = subcommand_usage("[host]")
|
|
1971
|
+
opts.on('-w','--wiki', "Open the wiki tab for this host") do
|
|
1972
|
+
options[:link_tab] = "wiki"
|
|
1973
|
+
end
|
|
1974
|
+
opts.on('--tab VALUE', String, "Open a specific tab") do |val|
|
|
1975
|
+
options[:link_tab] = val.to_s
|
|
1976
|
+
end
|
|
1977
|
+
build_common_options(opts, options, [:dry_run, :remote])
|
|
1978
|
+
opts.footer = "View a host in a web browser" + "\n" +
|
|
1979
|
+
"[host] is required. This is the name or id of a host. Supports 1-N [host] arguments."
|
|
1980
|
+
end
|
|
1981
|
+
optparse.parse!(args)
|
|
1982
|
+
if args.count != 1
|
|
1983
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
|
1984
|
+
end
|
|
1985
|
+
connect(options)
|
|
1986
|
+
id_list = parse_id_list(args)
|
|
1987
|
+
return run_command_for_each_arg(id_list) do |arg|
|
|
1988
|
+
_view(arg, options)
|
|
1989
|
+
end
|
|
1990
|
+
end
|
|
1991
|
+
|
|
1992
|
+
def _view(arg, options={})
|
|
1993
|
+
begin
|
|
1994
|
+
host = find_host_by_name_or_id(arg)
|
|
1995
|
+
return 1 if host.nil?
|
|
1996
|
+
|
|
1997
|
+
link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/infrastructure/servers/#{host['id']}"
|
|
1998
|
+
if options[:link_tab]
|
|
1999
|
+
link << "#!#{options[:link_tab]}"
|
|
2000
|
+
end
|
|
2001
|
+
|
|
2002
|
+
if options[:dry_run]
|
|
2003
|
+
puts MtnCloud::Util.open_url_command(link)
|
|
2004
|
+
return 0
|
|
2005
|
+
end
|
|
2006
|
+
return MtnCloud::Util.open_url(link)
|
|
2007
|
+
rescue RestClient::Exception => e
|
|
2008
|
+
print_rest_exception(e, options)
|
|
2009
|
+
exit 1
|
|
2010
|
+
end
|
|
2011
|
+
end
|
|
2012
|
+
|
|
2013
|
+
def wiki(args)
|
|
2014
|
+
options = {}
|
|
2015
|
+
params = {}
|
|
2016
|
+
open_wiki_link = false
|
|
2017
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2018
|
+
opts.banner = subcommand_usage("[host]")
|
|
2019
|
+
opts.on('--view', '--view', "View wiki page in web browser.") do
|
|
2020
|
+
open_wiki_link = true
|
|
2021
|
+
end
|
|
2022
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
|
2023
|
+
opts.footer = "View wiki page details for a host." + "\n" +
|
|
2024
|
+
"[host] is required. This is the name or id of a host."
|
|
2025
|
+
end
|
|
2026
|
+
optparse.parse!(args)
|
|
2027
|
+
if args.count != 1
|
|
2028
|
+
puts_error "#{MtnCloud::Terminal.angry_prompt}wrong number of arguments. Expected 1 and received #{args.count} #{args.inspect}\n#{optparse}"
|
|
2029
|
+
return 1
|
|
2030
|
+
end
|
|
2031
|
+
connect(options)
|
|
2032
|
+
|
|
2033
|
+
begin
|
|
2034
|
+
host = find_host_by_name_or_id(args[0])
|
|
2035
|
+
return 1 if host.nil?
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
@servers_interface.setopts(options)
|
|
2039
|
+
if options[:dry_run]
|
|
2040
|
+
print_dry_run @servers_interface.dry.wiki(host["id"], params)
|
|
2041
|
+
return
|
|
2042
|
+
end
|
|
2043
|
+
json_response = @servers_interface.wiki(host["id"], params)
|
|
2044
|
+
page = json_response['page']
|
|
2045
|
+
|
|
2046
|
+
render_result = render_with_format(json_response, options, 'page')
|
|
2047
|
+
return 0 if render_result
|
|
2048
|
+
|
|
2049
|
+
if page
|
|
2050
|
+
|
|
2051
|
+
# my_terminal.exec("wiki get #{page['id']}")
|
|
2052
|
+
|
|
2053
|
+
print_h1 "Host Wiki Page: #{host['name']}"
|
|
2054
|
+
# print_h1 "Wiki Page Details"
|
|
2055
|
+
print cyan
|
|
2056
|
+
|
|
2057
|
+
print_description_list({
|
|
2058
|
+
"Page ID" => 'id',
|
|
2059
|
+
"Name" => 'name',
|
|
2060
|
+
#"Category" => 'category',
|
|
2061
|
+
#"Ref Type" => 'refType',
|
|
2062
|
+
#"Ref ID" => 'refId',
|
|
2063
|
+
#"Owner" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
|
2064
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
|
2065
|
+
"Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' },
|
|
2066
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
|
2067
|
+
"Updated By" => lambda {|it| it['updatedBy'] ? it['updatedBy']['username'] : '' }
|
|
2068
|
+
}, page)
|
|
2069
|
+
print reset,"\n"
|
|
2070
|
+
|
|
2071
|
+
print_h2 "Page Content"
|
|
2072
|
+
print cyan, page['content'], reset, "\n"
|
|
2073
|
+
|
|
2074
|
+
else
|
|
2075
|
+
print "\n"
|
|
2076
|
+
print cyan, "No wiki page found.", reset, "\n"
|
|
2077
|
+
end
|
|
2078
|
+
print reset,"\n"
|
|
2079
|
+
|
|
2080
|
+
if open_wiki_link
|
|
2081
|
+
return view_wiki([args[0]])
|
|
2082
|
+
end
|
|
2083
|
+
|
|
2084
|
+
return 0
|
|
2085
|
+
rescue RestClient::Exception => e
|
|
2086
|
+
print_rest_exception(e, options)
|
|
2087
|
+
exit 1
|
|
2088
|
+
end
|
|
2089
|
+
end
|
|
2090
|
+
|
|
2091
|
+
def view_wiki(args)
|
|
2092
|
+
params = {}
|
|
2093
|
+
options = {}
|
|
2094
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2095
|
+
opts.banner = subcommand_usage("[id]")
|
|
2096
|
+
build_common_options(opts, options, [:dry_run, :remote])
|
|
2097
|
+
opts.footer = "View host wiki page in a web browser" + "\n" +
|
|
2098
|
+
"[host] is required. This is the name or id of a host."
|
|
2099
|
+
end
|
|
2100
|
+
optparse.parse!(args)
|
|
2101
|
+
if args.count != 1
|
|
2102
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
|
2103
|
+
end
|
|
2104
|
+
connect(options)
|
|
2105
|
+
begin
|
|
2106
|
+
host = find_host_by_name_or_id(args[0])
|
|
2107
|
+
return 1 if host.nil?
|
|
2108
|
+
|
|
2109
|
+
link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/infrastructure/servers/#{host['id']}#!wiki"
|
|
2110
|
+
|
|
2111
|
+
open_command = nil
|
|
2112
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
|
2113
|
+
open_command = "start #{link}"
|
|
2114
|
+
elsif RbConfig::CONFIG['host_os'] =~ /darwin/
|
|
2115
|
+
open_command = "open #{link}"
|
|
2116
|
+
elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
|
|
2117
|
+
open_command = "xdg-open #{link}"
|
|
2118
|
+
end
|
|
2119
|
+
|
|
2120
|
+
if options[:dry_run]
|
|
2121
|
+
puts "system: #{open_command}"
|
|
2122
|
+
return 0
|
|
2123
|
+
end
|
|
2124
|
+
|
|
2125
|
+
system(open_command)
|
|
2126
|
+
|
|
2127
|
+
return 0
|
|
2128
|
+
rescue RestClient::Exception => e
|
|
2129
|
+
print_rest_exception(e, options)
|
|
2130
|
+
exit 1
|
|
2131
|
+
end
|
|
2132
|
+
end
|
|
2133
|
+
|
|
2134
|
+
def update_wiki(args)
|
|
2135
|
+
options = {}
|
|
2136
|
+
params = {}
|
|
2137
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2138
|
+
opts.banner = subcommand_usage("[host] [options]")
|
|
2139
|
+
build_option_type_options(opts, options, update_wiki_page_option_types)
|
|
2140
|
+
opts.on('--file FILE', "File containing the wiki content. This can be used instead of --content") do |filename|
|
|
2141
|
+
full_filename = File.expand_path(filename)
|
|
2142
|
+
if File.exist?(full_filename)
|
|
2143
|
+
params['content'] = File.read(full_filename)
|
|
2144
|
+
else
|
|
2145
|
+
print_red_alert "File not found: #{full_filename}"
|
|
2146
|
+
return 1
|
|
2147
|
+
end
|
|
2148
|
+
# use the filename as the name by default.
|
|
2149
|
+
if !params['name']
|
|
2150
|
+
params['name'] = File.basename(full_filename)
|
|
2151
|
+
end
|
|
2152
|
+
end
|
|
2153
|
+
opts.on(nil, '--clear', "Clear current page content") do |val|
|
|
2154
|
+
params['content'] = ""
|
|
2155
|
+
end
|
|
2156
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
|
2157
|
+
end
|
|
2158
|
+
optparse.parse!(args)
|
|
2159
|
+
if args.count != 1
|
|
2160
|
+
puts_error "#{MtnCloud::Terminal.angry_prompt}wrong number of arguments. Expected 1 and received #{args.count} #{args.inspect}\n#{optparse}"
|
|
2161
|
+
return 1
|
|
2162
|
+
end
|
|
2163
|
+
connect(options)
|
|
2164
|
+
|
|
2165
|
+
begin
|
|
2166
|
+
host = find_host_by_name_or_id(args[0])
|
|
2167
|
+
return 1 if host.nil?
|
|
2168
|
+
# construct payload
|
|
2169
|
+
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
2170
|
+
payload = nil
|
|
2171
|
+
if options[:payload]
|
|
2172
|
+
payload = options[:payload]
|
|
2173
|
+
payload.deep_merge!({'page' => passed_options}) unless passed_options.empty?
|
|
2174
|
+
else
|
|
2175
|
+
payload = {
|
|
2176
|
+
'page' => {
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
# allow arbitrary -O options
|
|
2180
|
+
payload.deep_merge!({'page' => passed_options}) unless passed_options.empty?
|
|
2181
|
+
# prompt for options
|
|
2182
|
+
#params = MtnCloud::Cli::OptionTypes.prompt(update_wiki_page_option_types, options[:options], @api_client, options[:params])
|
|
2183
|
+
#params = passed_options
|
|
2184
|
+
params.deep_merge!(passed_options)
|
|
2185
|
+
|
|
2186
|
+
if params.empty?
|
|
2187
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
|
2188
|
+
end
|
|
2189
|
+
|
|
2190
|
+
payload.deep_merge!({'page' => params}) unless params.empty?
|
|
2191
|
+
end
|
|
2192
|
+
@servers_interface.setopts(options)
|
|
2193
|
+
if options[:dry_run]
|
|
2194
|
+
print_dry_run @servers_interface.dry.update_wiki(host["id"], payload)
|
|
2195
|
+
return
|
|
2196
|
+
end
|
|
2197
|
+
json_response = @servers_interface.update_wiki(host["id"], payload)
|
|
2198
|
+
|
|
2199
|
+
if options[:json]
|
|
2200
|
+
puts as_json(json_response, options)
|
|
2201
|
+
else
|
|
2202
|
+
print_green_success "Updated wiki page for host #{host['name']}"
|
|
2203
|
+
wiki([host['id']])
|
|
2204
|
+
end
|
|
2205
|
+
return 0
|
|
2206
|
+
rescue RestClient::Exception => e
|
|
2207
|
+
print_rest_exception(e, options)
|
|
2208
|
+
exit 1
|
|
2209
|
+
end
|
|
2210
|
+
end
|
|
2211
|
+
|
|
2212
|
+
def snapshots(args)
|
|
2213
|
+
options = {}
|
|
2214
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2215
|
+
opts.banner = subcommand_usage("[host] [snapshot]")
|
|
2216
|
+
# no pagination yet
|
|
2217
|
+
# build_standard_list_options(opts, options)
|
|
2218
|
+
build_standard_list_options(opts, options, [:details])
|
|
2219
|
+
opts.footer = <<-EOT
|
|
2220
|
+
List snapshots for a host.
|
|
2221
|
+
[host] is required. This is the name or id of a host.
|
|
2222
|
+
[snapshot] is optional. This is the name or id of a snapshot.
|
|
2223
|
+
EOT
|
|
2224
|
+
end
|
|
2225
|
+
optparse.parse!(args)
|
|
2226
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
2227
|
+
connect(options)
|
|
2228
|
+
begin
|
|
2229
|
+
server = find_host_by_name_or_id(args[0])
|
|
2230
|
+
return 1 if server.nil?
|
|
2231
|
+
params = {}
|
|
2232
|
+
@servers_interface.setopts(options)
|
|
2233
|
+
if options[:dry_run]
|
|
2234
|
+
print_dry_run @servers_interface.dry.snapshots(server['id'], params)
|
|
2235
|
+
return
|
|
2236
|
+
end
|
|
2237
|
+
json_response = @servers_interface.snapshots(server['id'], params)
|
|
2238
|
+
snapshots = json_response['snapshots']
|
|
2239
|
+
# [snapshots] is done with post api filtering by id or name or externalId
|
|
2240
|
+
if args[1]
|
|
2241
|
+
if args[1] =~ /\A\d{1,}\Z/
|
|
2242
|
+
snapshots = snapshots.select {|it| it['id'].to_s == args[1] }
|
|
2243
|
+
else
|
|
2244
|
+
# match beginning of name of externalId
|
|
2245
|
+
snapshots = snapshots.select {|it| it['name'].to_s.index(args[1]) == 0 || it['externalId'].to_s.index(args[1]) == 0 }
|
|
2246
|
+
end
|
|
2247
|
+
json_response['snapshots'] = snapshots # update response for -j filtering too
|
|
2248
|
+
end
|
|
2249
|
+
render_response(json_response, options, 'snapshots') do
|
|
2250
|
+
print_h1 "Snapshots: #{server['name']}", [], options
|
|
2251
|
+
if snapshots.empty?
|
|
2252
|
+
if args[1]
|
|
2253
|
+
print cyan,"No snapshots found for '#{args[1]}'",reset,"\n"
|
|
2254
|
+
elsif
|
|
2255
|
+
print cyan,"No snapshots found",reset,"\n"
|
|
2256
|
+
end
|
|
2257
|
+
print reset, "\n"
|
|
2258
|
+
else
|
|
2259
|
+
if options[:details]
|
|
2260
|
+
# this actually makes a request for each one here so don't go crazy...
|
|
2261
|
+
if snapshots.size > 3
|
|
2262
|
+
print cyan, "Showing first 3 snapshots. Use the ID to get more details.", reset, "\n"
|
|
2263
|
+
snapshots = snapshots.first(3)
|
|
2264
|
+
end
|
|
2265
|
+
snapshots.each do |snapshot|
|
|
2266
|
+
MtnCloud::Cli::Snapshots.new.handle(["get", snapshot['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
2267
|
+
end
|
|
2268
|
+
else
|
|
2269
|
+
# Snapshots List
|
|
2270
|
+
snapshot_column_definitions = {
|
|
2271
|
+
"ID" => lambda {|it| it['id'] },
|
|
2272
|
+
"Name" => lambda {|it| it['name'] },
|
|
2273
|
+
"Description" => lambda {|it| it['description'] },
|
|
2274
|
+
# "Type" => lambda {|it| it['snapshotType'] },
|
|
2275
|
+
"Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
|
|
2276
|
+
"Status" => lambda {|it| format_snapshot_status(it) }
|
|
2277
|
+
}
|
|
2278
|
+
print cyan
|
|
2279
|
+
print as_pretty_table(snapshots, snapshot_column_definitions.upcase_keys!, options)
|
|
2280
|
+
print_results_pagination({size: snapshots.size, total: snapshots.size})
|
|
2281
|
+
print reset, "\n"
|
|
2282
|
+
end
|
|
2283
|
+
end
|
|
2284
|
+
end
|
|
2285
|
+
return 0
|
|
2286
|
+
rescue RestClient::Exception => e
|
|
2287
|
+
print_rest_exception(e, options)
|
|
2288
|
+
exit 1
|
|
2289
|
+
end
|
|
2290
|
+
end
|
|
2291
|
+
|
|
2292
|
+
def software(args)
|
|
2293
|
+
options = {}
|
|
2294
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2295
|
+
opts.banner = subcommand_usage("[host]")
|
|
2296
|
+
build_standard_list_options(opts, options)
|
|
2297
|
+
opts.footer = <<-EOT
|
|
2298
|
+
List installed software for a host.
|
|
2299
|
+
[host] is required. This is the name or id of a host.
|
|
2300
|
+
EOT
|
|
2301
|
+
end
|
|
2302
|
+
optparse.parse!(args)
|
|
2303
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2304
|
+
connect(options)
|
|
2305
|
+
begin
|
|
2306
|
+
server = find_host_by_name_or_id(args[0])
|
|
2307
|
+
return 1 if server.nil?
|
|
2308
|
+
params = {}
|
|
2309
|
+
params.merge!(parse_list_options(options))
|
|
2310
|
+
@servers_interface.setopts(options)
|
|
2311
|
+
if options[:dry_run]
|
|
2312
|
+
print_dry_run @servers_interface.dry.software(server['id'], params)
|
|
2313
|
+
return
|
|
2314
|
+
end
|
|
2315
|
+
json_response = @servers_interface.software(server['id'], params)
|
|
2316
|
+
software = json_response['software']
|
|
2317
|
+
render_response(json_response, options, 'software') do
|
|
2318
|
+
print_h1 "Software: #{server['name']}", [], options
|
|
2319
|
+
if software.empty?
|
|
2320
|
+
print cyan,"No software found",reset,"\n"
|
|
2321
|
+
else
|
|
2322
|
+
software_column_definitions = {
|
|
2323
|
+
# "ID" => lambda {|it| it['id'] },
|
|
2324
|
+
"Name" => lambda {|it| it['name'] },
|
|
2325
|
+
"Version" => lambda {|it| it['packageVersion'] },
|
|
2326
|
+
"Publisher" => lambda {|it| it['packagePublisher'] },
|
|
2327
|
+
# "Release" => lambda {|it| it['packageRelease'] },
|
|
2328
|
+
# "Type" => lambda {|it| it['packageType'] },
|
|
2329
|
+
# "Architecture" => lambda {|it| it['architecture'] },
|
|
2330
|
+
# "Install Date" => lambda {|it| format_local_dt(it['installDate']) },
|
|
2331
|
+
}
|
|
2332
|
+
print cyan
|
|
2333
|
+
print as_pretty_table(software, software_column_definitions.upcase_keys!, options)
|
|
2334
|
+
print_results_pagination({size: software.size, total: software.size})
|
|
2335
|
+
end
|
|
2336
|
+
print reset, "\n"
|
|
2337
|
+
end
|
|
2338
|
+
return 0
|
|
2339
|
+
rescue RestClient::Exception => e
|
|
2340
|
+
print_rest_exception(e, options)
|
|
2341
|
+
exit 1
|
|
2342
|
+
end
|
|
2343
|
+
end
|
|
2344
|
+
|
|
2345
|
+
def software_sync(args)
|
|
2346
|
+
options = {}
|
|
2347
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2348
|
+
opts.banner = subcommand_usage("[host]")
|
|
2349
|
+
build_standard_update_options(opts, options)
|
|
2350
|
+
opts.footer = <<-EOT
|
|
2351
|
+
Sync installed software for a host.
|
|
2352
|
+
[host] is required. This is the name or id of a host.
|
|
2353
|
+
EOT
|
|
2354
|
+
end
|
|
2355
|
+
optparse.parse!(args)
|
|
2356
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2357
|
+
connect(options)
|
|
2358
|
+
begin
|
|
2359
|
+
server = find_host_by_name_or_id(args[0])
|
|
2360
|
+
return 1 if server.nil?
|
|
2361
|
+
payload = {}
|
|
2362
|
+
if options[:payload]
|
|
2363
|
+
payload = options[:payload]
|
|
2364
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2365
|
+
else
|
|
2366
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2367
|
+
end
|
|
2368
|
+
params = {}
|
|
2369
|
+
params.merge!(parse_query_options(options))
|
|
2370
|
+
@servers_interface.setopts(options)
|
|
2371
|
+
if options[:dry_run]
|
|
2372
|
+
print_dry_run @servers_interface.dry.software_sync(server['id'], payload, params)
|
|
2373
|
+
return
|
|
2374
|
+
end
|
|
2375
|
+
json_response = @servers_interface.software_sync(server['id'], payload, params)
|
|
2376
|
+
render_response(json_response, options) do
|
|
2377
|
+
print_green_success "Syncing software for host #{server['name']}"
|
|
2378
|
+
#get([server['id']])
|
|
2379
|
+
end
|
|
2380
|
+
return 0
|
|
2381
|
+
rescue RestClient::Exception => e
|
|
2382
|
+
print_rest_exception(e, options)
|
|
2383
|
+
exit 1
|
|
2384
|
+
end
|
|
2385
|
+
end
|
|
2386
|
+
|
|
2387
|
+
def update_network_label(args)
|
|
2388
|
+
options = {}
|
|
2389
|
+
params = {}
|
|
2390
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2391
|
+
opts.banner = subcommand_usage("[server] [options]")
|
|
2392
|
+
opts.on('--network NETWORK', "Network Interface ID" ) do |val|
|
|
2393
|
+
options[:network] = val
|
|
2394
|
+
end
|
|
2395
|
+
opts.on('--label LABEL', "label") do |val|
|
|
2396
|
+
options[:label] = val
|
|
2397
|
+
end
|
|
2398
|
+
opts.footer = "Change the label of a Network Interface.\n" +
|
|
2399
|
+
"Editing an Interface will not apply changes to the physical hardware. The purpose is for a manual override or data correction (mostly for self managed or baremetal servers where cloud sync is not available)\n" +
|
|
2400
|
+
"[name or id] is required. The name or the id of the server.\n" +
|
|
2401
|
+
"[network] ID of the Network Interface. (optional).\n" +
|
|
2402
|
+
"[label] New Label name for the Network Interface (optional)"
|
|
2403
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
|
2404
|
+
end
|
|
2405
|
+
optparse.parse!(args)
|
|
2406
|
+
if args.count != 1
|
|
2407
|
+
puts_error "#{MtnCloud::Terminal.angry_prompt}wrong number of arguments. Expected 1 and received #{args.count} #{args.inspect}\n#{optparse}"
|
|
2408
|
+
return 1
|
|
2409
|
+
end
|
|
2410
|
+
connect(options)
|
|
2411
|
+
|
|
2412
|
+
begin
|
|
2413
|
+
host = find_host_by_name_or_id(args[0])
|
|
2414
|
+
return 1 if host.nil?
|
|
2415
|
+
|
|
2416
|
+
network_id = options[:network]
|
|
2417
|
+
if network_id != nil && network_id.to_i == 0
|
|
2418
|
+
print_red_alert "network must be an ID/integer above 0, not a name/string value."
|
|
2419
|
+
network_id = nil
|
|
2420
|
+
end
|
|
2421
|
+
|
|
2422
|
+
|
|
2423
|
+
if !network_id
|
|
2424
|
+
available_networks = get_available_networks(host)
|
|
2425
|
+
network_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'network', 'fieldLabel' => 'Network', 'type' => 'select', 'selectOptions' => available_networks, 'required' => true, 'defaultValue' => available_networks[0], 'description' => "The networks available for relabeling"}], options[:options])
|
|
2426
|
+
network_id = network_prompt['network']
|
|
2427
|
+
end
|
|
2428
|
+
|
|
2429
|
+
label = options[:label]
|
|
2430
|
+
while label.nil? do
|
|
2431
|
+
label_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'label', 'fieldLabel' => 'Label', 'type' => 'text', 'required' => true}], options[:options])
|
|
2432
|
+
label = label_prompt['label']
|
|
2433
|
+
end
|
|
2434
|
+
payload = { "name" => label }
|
|
2435
|
+
if options[:dry_run]
|
|
2436
|
+
print_dry_run @servers_interface.dry.update_network_label(network_id, host["id"], payload)
|
|
2437
|
+
return
|
|
2438
|
+
end
|
|
2439
|
+
json_response = @servers_interface.update_network_label(network_id, host["id"], payload)
|
|
2440
|
+
if options[:json]
|
|
2441
|
+
puts as_json(json_response, options)
|
|
2442
|
+
else
|
|
2443
|
+
print_green_success "Updated label for host #{host['name']} network #{network_id} to #{label}"
|
|
2444
|
+
end
|
|
2445
|
+
return 0
|
|
2446
|
+
rescue RestClient::Exception => e
|
|
2447
|
+
print_rest_exception(e, options)
|
|
2448
|
+
exit 1
|
|
2449
|
+
end
|
|
2450
|
+
end
|
|
2451
|
+
|
|
2452
|
+
|
|
2453
|
+
def maintenance(args)
|
|
2454
|
+
options = {}
|
|
2455
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2456
|
+
opts.banner = subcommand_usage("[host]")
|
|
2457
|
+
opts.on('--ignoreDaemonsets [on|off]', String, "Ignore Daemonsets") do |val|
|
|
2458
|
+
options[:ignoreDaemonsets] = (val.to_s.empty? || val.to_s == 'on' || val.to_s == 'true')
|
|
2459
|
+
end
|
|
2460
|
+
opts.on('--force [on|off]', String, "Force") do |val|
|
|
2461
|
+
options[:force] = (val.to_s.empty? || val.to_s == 'on' || val.to_s == 'true')
|
|
2462
|
+
end
|
|
2463
|
+
opts.on('--deleteEmptyDir [on|off]', String, "Delete Empty Directories") do |val|
|
|
2464
|
+
options[:deleteEmptyDir] = (val.to_s.empty? || val.to_s == 'on' || val.to_s == 'true')
|
|
2465
|
+
end
|
|
2466
|
+
opts.on('--deleteLocalData [on|off]', String, "Delete Local Data") do |val|
|
|
2467
|
+
options[:deleteLocalData] = (val.to_s == 'on' || val.to_s == 'true')
|
|
2468
|
+
end
|
|
2469
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
2470
|
+
opts.footer = <<-EOT
|
|
2471
|
+
Enable maintenance mode for a host.
|
|
2472
|
+
[host] is required. This is the name or id of a host.
|
|
2473
|
+
EOT
|
|
2474
|
+
end
|
|
2475
|
+
optparse.parse!(args)
|
|
2476
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2477
|
+
connect(options)
|
|
2478
|
+
|
|
2479
|
+
server = find_host_by_name_or_id(args[0])
|
|
2480
|
+
return 1 if server.nil?
|
|
2481
|
+
|
|
2482
|
+
# Just let the API return this error instead
|
|
2483
|
+
|
|
2484
|
+
# # load server type to determine if maintenance mode is supported
|
|
2485
|
+
# server_type_id = server['computeServerType']['id']
|
|
2486
|
+
# server_type = @server_types_interface.get(server_type_id)['serverType']
|
|
2487
|
+
# if !server_type['hasMaintenanceMode']
|
|
2488
|
+
# raise_command_error "Server type does not support maintenance mode"
|
|
2489
|
+
# end
|
|
2490
|
+
|
|
2491
|
+
payload = {}
|
|
2492
|
+
|
|
2493
|
+
if server.dig('config', 'kubernetesRole')
|
|
2494
|
+
payload[:server] = {}
|
|
2495
|
+
payload[:server][:ignoreDaemonsets] = options.fetch(:ignoreDaemonsets) do
|
|
2496
|
+
prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'ignoreDaemonsets', 'fieldLabel' => 'Ignore Daemonsets', 'type' => 'checkbox', 'defaultValue' => true, 'required' => false}], options, @api_client, {})
|
|
2497
|
+
prompt['ignoreDaemonsets'] == 'on'
|
|
2498
|
+
end
|
|
2499
|
+
payload[:server][:force] = options.fetch(:force) do
|
|
2500
|
+
prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'force', 'fieldLabel' => 'Force', 'type' => 'checkbox', 'defaultValue' => true, 'required' => false}], options, @api_client, {})
|
|
2501
|
+
prompt['force'] == 'on'
|
|
2502
|
+
end
|
|
2503
|
+
payload[:server][:deleteEmptyDir] = options.fetch(:deleteEmptyDir) do
|
|
2504
|
+
prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'deleteEmptyDir', 'fieldLabel' => 'Delete Empty Directories', 'type' => 'checkbox', 'defaultValue' => true, 'required' => false}], options, @api_client, {})
|
|
2505
|
+
prompt['deleteEmptyDir'] == 'on'
|
|
2506
|
+
end
|
|
2507
|
+
payload[:server][:deleteLocalData] = options.fetch(:deleteLocalData) do
|
|
2508
|
+
prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'deleteLocalData', 'fieldLabel' => 'Delete Local Data', 'type' => 'checkbox', 'defaultValue' => false, 'required' => false}], options, @api_client, {})
|
|
2509
|
+
prompt['deleteLocalData'] == 'on'
|
|
2510
|
+
end
|
|
2511
|
+
end
|
|
2512
|
+
|
|
2513
|
+
if options[:payload]
|
|
2514
|
+
payload = options[:payload]
|
|
2515
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2516
|
+
else
|
|
2517
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2518
|
+
end
|
|
2519
|
+
params = {}
|
|
2520
|
+
params.merge!(parse_query_options(options))
|
|
2521
|
+
|
|
2522
|
+
confirm!("Are you sure you would like to enable maintenance mode on host '#{server['name']}'?", options)
|
|
2523
|
+
|
|
2524
|
+
@servers_interface.setopts(options)
|
|
2525
|
+
if options[:dry_run]
|
|
2526
|
+
print_dry_run @servers_interface.dry.maintenance(server['id'], payload, params)
|
|
2527
|
+
return
|
|
2528
|
+
end
|
|
2529
|
+
json_response = @servers_interface.maintenance(server['id'], payload, params)
|
|
2530
|
+
render_response(json_response, options) do
|
|
2531
|
+
print_green_success "Maintenance mode enabled for host #{server['name']}"
|
|
2532
|
+
#get([server['id']])
|
|
2533
|
+
end
|
|
2534
|
+
return 0, nil
|
|
2535
|
+
end
|
|
2536
|
+
|
|
2537
|
+
def leave_maintenance(args)
|
|
2538
|
+
options = {}
|
|
2539
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2540
|
+
opts.banner = subcommand_usage("[host]")
|
|
2541
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
2542
|
+
opts.footer = <<-EOT
|
|
2543
|
+
Disable maintenance mode for a host.
|
|
2544
|
+
[host] is required. This is the name or id of a host.
|
|
2545
|
+
EOT
|
|
2546
|
+
end
|
|
2547
|
+
optparse.parse!(args)
|
|
2548
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2549
|
+
connect(options)
|
|
2550
|
+
|
|
2551
|
+
server = find_host_by_name_or_id(args[0])
|
|
2552
|
+
return 1 if server.nil?
|
|
2553
|
+
|
|
2554
|
+
# Just let the API return this error instead
|
|
2555
|
+
|
|
2556
|
+
# # load server type to determine if maintenance mode is supported
|
|
2557
|
+
# server_type_id = server['computeServerType']['id']
|
|
2558
|
+
# server_type = @server_types_interface.get(server_type_id)['serverType']
|
|
2559
|
+
# if !server_type['hasMaintenanceMode']
|
|
2560
|
+
# raise_command_error "Server type does not support maintenance mode"
|
|
2561
|
+
# end
|
|
2562
|
+
|
|
2563
|
+
payload = {}
|
|
2564
|
+
if options[:payload]
|
|
2565
|
+
payload = options[:payload]
|
|
2566
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2567
|
+
else
|
|
2568
|
+
payload.deep_merge!(parse_passed_options(options))
|
|
2569
|
+
end
|
|
2570
|
+
params = {}
|
|
2571
|
+
params.merge!(parse_query_options(options))
|
|
2572
|
+
|
|
2573
|
+
confirm!("Are you sure you would like to leave maintenance mode on host '#{server['name']}'?", options)
|
|
2574
|
+
|
|
2575
|
+
@servers_interface.setopts(options)
|
|
2576
|
+
if options[:dry_run]
|
|
2577
|
+
print_dry_run @servers_interface.dry.leave_maintenance(server['id'], payload, params)
|
|
2578
|
+
return
|
|
2579
|
+
end
|
|
2580
|
+
json_response = @servers_interface.leave_maintenance(server['id'], payload, params)
|
|
2581
|
+
render_response(json_response, options) do
|
|
2582
|
+
print_green_success "Left Maintenance Mode for host #{server['name']}"
|
|
2583
|
+
#get([server['id']])
|
|
2584
|
+
end
|
|
2585
|
+
return 0, nil
|
|
2586
|
+
end
|
|
2587
|
+
|
|
2588
|
+
def placement(args)
|
|
2589
|
+
options = {}
|
|
2590
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2591
|
+
opts.banner = subcommand_usage("[host]")
|
|
2592
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
2593
|
+
opts.footer = <<-EOT
|
|
2594
|
+
Update placement for a host.
|
|
2595
|
+
[host] is required. This is the name or id of a host.
|
|
2596
|
+
EOT
|
|
2597
|
+
end
|
|
2598
|
+
optparse.parse!(args)
|
|
2599
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2600
|
+
connect(options)
|
|
2601
|
+
|
|
2602
|
+
server = find_host_by_name_or_id(args[0])
|
|
2603
|
+
return 1 if server.nil?
|
|
2604
|
+
payload = {}
|
|
2605
|
+
if options[:payload]
|
|
2606
|
+
payload = options[:payload]
|
|
2607
|
+
payload.deep_merge!({'server' => parse_passed_options(options)})
|
|
2608
|
+
else
|
|
2609
|
+
payload.deep_merge!({'server' => parse_passed_options(options)})
|
|
2610
|
+
# prompt
|
|
2611
|
+
# Host (preferredParentServer.id)
|
|
2612
|
+
if payload['server']['host']
|
|
2613
|
+
options[:options] = payload['server'].delete('host')
|
|
2614
|
+
end
|
|
2615
|
+
default_host = (server['preferredParentServer'] ? server['preferredParentServer']['id'] : (server['parentServer'] ? server['parentServer']['id'] : nil))
|
|
2616
|
+
host = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'host', 'type' => 'select', 'fieldLabel' => 'Host', 'optionSource' => 'parentServers', 'required' => false, 'description' => 'Choose the preferred parent host for this virtual machine to be placed on.', 'defaultValue' => default_host}],options[:options],@api_client,{'serverId' => server['id']})['host']
|
|
2617
|
+
if !host.to_s.empty?
|
|
2618
|
+
payload['server']['preferredParentServer'] = {'id' => host}
|
|
2619
|
+
end
|
|
2620
|
+
|
|
2621
|
+
|
|
2622
|
+
# Placement Strategy (placementStrategy)
|
|
2623
|
+
placement_strategy = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'placementStrategy', 'type' => 'select', 'fieldLabel' => 'Placement Strategy', 'optionSource' => 'placementStrategies', 'required' => false, 'description' => 'Choose the placement strategy for this virtual machine.', 'defaultValue' => server['placementStrategy']}],options[:options],@api_client,{'serverId' => server['id']})['placementStrategy']
|
|
2624
|
+
if !placement_strategy.to_s.empty?
|
|
2625
|
+
payload['server']['placementStrategy'] = placement_strategy
|
|
2626
|
+
end
|
|
2627
|
+
end
|
|
2628
|
+
params = {}
|
|
2629
|
+
params.merge!(parse_query_options(options))
|
|
2630
|
+
|
|
2631
|
+
confirm!("Are you sure you would like to update placement for host '#{server['name']}'?", options)
|
|
2632
|
+
|
|
2633
|
+
@servers_interface.setopts(options)
|
|
2634
|
+
if options[:dry_run]
|
|
2635
|
+
print_dry_run @servers_interface.dry.placement(server['id'], payload, params)
|
|
2636
|
+
return
|
|
2637
|
+
end
|
|
2638
|
+
json_response = @servers_interface.placement(server['id'], payload, params)
|
|
2639
|
+
render_response(json_response, options) do
|
|
2640
|
+
print_green_success "Maintenance mode enabled for host #{server['name']}"
|
|
2641
|
+
#get([server['id']])
|
|
2642
|
+
end
|
|
2643
|
+
return 0, nil
|
|
2644
|
+
end
|
|
2645
|
+
|
|
2646
|
+
def snapshot(args)
|
|
2647
|
+
options = {}
|
|
2648
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2649
|
+
opts.banner = subcommand_usage("[host]")
|
|
2650
|
+
opts.on( '--name VALUE', String, "Snapshot Name. Default is \"{name}.{timestamp}\"" ) do |val|
|
|
2651
|
+
options[:options]['name'] = val
|
|
2652
|
+
end
|
|
2653
|
+
opts.on( '--description VALUE', String, "Snapshot Description." ) do |val|
|
|
2654
|
+
options[:options]['description'] = val
|
|
2655
|
+
end
|
|
2656
|
+
opts.on('--memory-snapshot [on|off]', String, "Memory Snapshot? Whether to include the memory state in the snapshot.") do |val|
|
|
2657
|
+
options[:options]['memorySnapshot'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
|
|
2658
|
+
end
|
|
2659
|
+
opts.on('--for-export [on|off]', String, "For Export? Indicates the snapshot is intended for export to storage.") do |val|
|
|
2660
|
+
options[:options]['forExport'] = val.to_s == '' || val.to_s == 'on' || val.to_s == 'true'
|
|
2661
|
+
end
|
|
2662
|
+
opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
|
|
2663
|
+
options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
|
|
2664
|
+
end
|
|
2665
|
+
opts.on(nil, '--no-refresh', "Do not refresh" ) do
|
|
2666
|
+
options[:no_refresh] = true
|
|
2667
|
+
end
|
|
2668
|
+
build_standard_add_options(opts, options, [:auto_confirm])
|
|
2669
|
+
opts.footer = <<-EOT
|
|
2670
|
+
Create a snapshot for a host.
|
|
2671
|
+
[host] is required. This is the name or id of a host
|
|
2672
|
+
EOT
|
|
2673
|
+
end
|
|
2674
|
+
optparse.parse!(args)
|
|
2675
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
2676
|
+
connect(options)
|
|
2677
|
+
server = find_host_by_name_or_id(args[0])
|
|
2678
|
+
payload = {}
|
|
2679
|
+
if options[:payload]
|
|
2680
|
+
payload = options[:payload]
|
|
2681
|
+
payload.deep_merge!({'snapshot' => parse_passed_options(options)})
|
|
2682
|
+
else
|
|
2683
|
+
payload.deep_merge!({'snapshot' => parse_passed_options(options)})
|
|
2684
|
+
# prompt for name and description
|
|
2685
|
+
name = prompt_value({'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Snapshot Name', 'description' => "Snapshot Name. Default is \"{name}.{timestamp}\""}, options)
|
|
2686
|
+
payload['snapshot']['name'] = name if !name.to_s.empty?
|
|
2687
|
+
description = prompt_value({'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'description' => "Snapshot Description."}, options)
|
|
2688
|
+
payload['snapshot']['description'] = description if !description.to_s.empty?
|
|
2689
|
+
# need to GET provision type for some settings...
|
|
2690
|
+
provision_type = nil
|
|
2691
|
+
begin
|
|
2692
|
+
provision_type_id = server['computeServerType']['provisionTypeId'] rescue nil
|
|
2693
|
+
if provision_type_id
|
|
2694
|
+
provision_type = @provision_types_interface.get(provision_type_id)['provisionType']
|
|
2695
|
+
end
|
|
2696
|
+
rescue => ex
|
|
2697
|
+
MtnCloud::Logging::DarkPrinter.puts "Failed to load provision type!" if MtnCloud::Logging.debug?
|
|
2698
|
+
end
|
|
2699
|
+
if provision_type && provision_type['hasMemorySnapshots']
|
|
2700
|
+
# prompt for memorySnapshot
|
|
2701
|
+
memory_snapshot = prompt_value({'fieldName' => 'memorySnapshot', 'type' => 'checkbox', 'fieldLabel' => 'Memory Snapshot?', 'description' => "Snapshot Description."}, options)
|
|
2702
|
+
payload['snapshot']['memorySnapshot'] = memory_snapshot if !memory_snapshot.to_s.empty?
|
|
2703
|
+
end
|
|
2704
|
+
# convert "on" and "off" to true/false
|
|
2705
|
+
payload.booleanize!
|
|
2706
|
+
end
|
|
2707
|
+
unless options[:yes] || ::MtnCloud::Cli::OptionTypes::confirm("Are you sure you would like to snapshot the host '#{server['name']}'?", options)
|
|
2708
|
+
exit 1
|
|
2709
|
+
end
|
|
2710
|
+
@servers_interface.setopts(options)
|
|
2711
|
+
if options[:dry_run]
|
|
2712
|
+
print_dry_run @servers_interface.dry.snapshot(server['id'], payload)
|
|
2713
|
+
return
|
|
2714
|
+
end
|
|
2715
|
+
json_response = @servers_interface.snapshot(server['id'], payload)
|
|
2716
|
+
render_response(json_response, options) do
|
|
2717
|
+
print_green_success "Snapshot initiated."
|
|
2718
|
+
process_id = json_response['processIds'][0] rescue nil
|
|
2719
|
+
if process_id
|
|
2720
|
+
unless options[:no_refresh]
|
|
2721
|
+
process = wait_for_process_execution(process_id, options)
|
|
2722
|
+
snapshot_id = process['resultId']
|
|
2723
|
+
if snapshot_id
|
|
2724
|
+
MtnCloud::Cli::Snapshots.new.handle(["get", snapshot_id] + (options[:remote] ? ["-r",options[:remote]] : []))
|
|
2725
|
+
end
|
|
2726
|
+
end
|
|
2727
|
+
else
|
|
2728
|
+
# puts "No process returned"
|
|
2729
|
+
end
|
|
2730
|
+
end
|
|
2731
|
+
return 0, nil
|
|
2732
|
+
end
|
|
2733
|
+
|
|
2734
|
+
def create_linked_clone(args)
|
|
2735
|
+
options = {}
|
|
2736
|
+
server = nil
|
|
2737
|
+
snapshot_id = nil
|
|
2738
|
+
|
|
2739
|
+
optparse = MtnCloud::Cli::OptionParser.new do |opts|
|
|
2740
|
+
opts.banner = subcommand_usage("[host]")
|
|
2741
|
+
opts.on("--snapshot ID", String, "Snapshot ID") do |val|
|
|
2742
|
+
snapshot_id = val
|
|
2743
|
+
end
|
|
2744
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
|
2745
|
+
opts.footer = "Create a linked clone using the selected snapshot of a Host." + "\n" +
|
|
2746
|
+
"[snapshotId] is required. This is the id of the snapshot which the clone will refer to."
|
|
2747
|
+
end
|
|
2748
|
+
|
|
2749
|
+
optparse.parse!(args)
|
|
2750
|
+
if args.count != 1
|
|
2751
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
|
2752
|
+
end
|
|
2753
|
+
connect(options)
|
|
2754
|
+
begin
|
|
2755
|
+
server = find_host_by_name_or_id(args[0])
|
|
2756
|
+
options[:options]['serverId'] = server['id']
|
|
2757
|
+
begin
|
|
2758
|
+
snapshot_options = @servers_interface.snapshots(server['id'], {})['snapshots'].collect {|it| {'name' => "#{it['name']} (#{it['id']})", 'value' => it['id']} }
|
|
2759
|
+
snapshot_prompt = MtnCloud::Cli::OptionTypes.prompt([{'fieldName' => 'snapshotId', 'type' => 'select', 'fieldLabel' => 'Snapshot', 'selectOptions' => snapshot_options, 'required' => true, 'description' => 'Select Snapshot.'}], {}, @api_client, options[:options])
|
|
2760
|
+
|
|
2761
|
+
if !snapshot_prompt['snapshotId'].to_s.empty?
|
|
2762
|
+
snapshot_id = snapshot_prompt['snapshotId']
|
|
2763
|
+
end
|
|
2764
|
+
rescue RestClient::Exception => e
|
|
2765
|
+
puts "Failed to load host snapshots"
|
|
2766
|
+
end
|
|
2767
|
+
|
|
2768
|
+
@servers_interface.setopts(options)
|
|
2769
|
+
|
|
2770
|
+
payload = {}
|
|
2771
|
+
if options[:dry_run]
|
|
2772
|
+
print_dry_run @servers_interface.dry.create_linked_clone(server['id'], snapshot_id, payload)
|
|
2773
|
+
return
|
|
2774
|
+
end
|
|
2775
|
+
|
|
2776
|
+
json_response = @servers_interface.create_linked_clone(server['id'], snapshot_id, payload)
|
|
2777
|
+
if options[:json]
|
|
2778
|
+
puts as_json(json_response, options)
|
|
2779
|
+
else
|
|
2780
|
+
print_green_success "Linked Clone creation initiated."
|
|
2781
|
+
end
|
|
2782
|
+
return 0
|
|
2783
|
+
|
|
2784
|
+
rescue RestClient::Exception => e
|
|
2785
|
+
print_rest_exception(e, options)
|
|
2786
|
+
exit 1
|
|
2787
|
+
end
|
|
2788
|
+
end
|
|
2789
|
+
|
|
2790
|
+
## Server Devices
|
|
2791
|
+
|
|
2792
|
+
def list_devices(args)
|
|
2793
|
+
MtnCloud::Cli::ServerDevicesCommand.new.list(args)
|
|
2794
|
+
end
|
|
2795
|
+
|
|
2796
|
+
def assign_device(args)
|
|
2797
|
+
MtnCloud::Cli::ServerDevicesCommand.new.assign(args)
|
|
2798
|
+
end
|
|
2799
|
+
|
|
2800
|
+
def attach_device(args)
|
|
2801
|
+
MtnCloud::Cli::ServerDevicesCommand.new.attach(args)
|
|
2802
|
+
end
|
|
2803
|
+
|
|
2804
|
+
def detach_device(args)
|
|
2805
|
+
MtnCloud::Cli::ServerDevicesCommand.new.detach(args)
|
|
2806
|
+
end
|
|
2807
|
+
|
|
2808
|
+
private
|
|
2809
|
+
|
|
2810
|
+
def find_host_by_id(id)
|
|
2811
|
+
begin
|
|
2812
|
+
json_response = @servers_interface.get(id.to_i)
|
|
2813
|
+
return json_response['server']
|
|
2814
|
+
rescue RestClient::Exception => e
|
|
2815
|
+
if e.response && e.response.code == 404
|
|
2816
|
+
print_red_alert "Host not found by id #{id}"
|
|
2817
|
+
exit 1
|
|
2818
|
+
else
|
|
2819
|
+
raise e
|
|
2820
|
+
end
|
|
2821
|
+
end
|
|
2822
|
+
end
|
|
2823
|
+
|
|
2824
|
+
def find_host_by_name(name, include_tenants=false)
|
|
2825
|
+
params = {name: name.to_s}
|
|
2826
|
+
params['includeTenants'] = true if include_tenants
|
|
2827
|
+
results = @servers_interface.list(params)
|
|
2828
|
+
if results['servers'].empty?
|
|
2829
|
+
print_red_alert "Server not found by name #{name}"
|
|
2830
|
+
exit 1
|
|
2831
|
+
elsif results['servers'].size > 1
|
|
2832
|
+
print_red_alert "Multiple Servers exist with the name '#{name}'"
|
|
2833
|
+
puts_error as_pretty_table(results['servers'], [:id, :name], {color:red})
|
|
2834
|
+
print_red_alert "Try using ID instead"
|
|
2835
|
+
exit 1
|
|
2836
|
+
end
|
|
2837
|
+
return results['servers'][0]
|
|
2838
|
+
end
|
|
2839
|
+
|
|
2840
|
+
def find_host_by_name_or_id(val, include_tenants=false)
|
|
2841
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
2842
|
+
return find_host_by_id(val)
|
|
2843
|
+
else
|
|
2844
|
+
return find_host_by_name(val, include_tenants)
|
|
2845
|
+
end
|
|
2846
|
+
end
|
|
2847
|
+
|
|
2848
|
+
def find_zone_by_name_or_id(group_id, val)
|
|
2849
|
+
zone = nil
|
|
2850
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
2851
|
+
json_results = @clouds_interface.get(val.to_i)
|
|
2852
|
+
zone = json_results['zone']
|
|
2853
|
+
if zone.nil?
|
|
2854
|
+
print_red_alert "Cloud not found by id #{val}"
|
|
2855
|
+
exit 1
|
|
2856
|
+
end
|
|
2857
|
+
else
|
|
2858
|
+
json_results = @clouds_interface.list({groupId: group_id, name: val})
|
|
2859
|
+
zone = json_results['zones'] ? json_results['zones'][0] : nil
|
|
2860
|
+
if zone.nil?
|
|
2861
|
+
print_red_alert "Cloud not found by name #{val}"
|
|
2862
|
+
exit 1
|
|
2863
|
+
end
|
|
2864
|
+
end
|
|
2865
|
+
return zone
|
|
2866
|
+
end
|
|
2867
|
+
|
|
2868
|
+
def find_server_type(zone, name)
|
|
2869
|
+
server_type = zone['serverTypes'].select do |sv_type|
|
|
2870
|
+
(sv_type['name'].downcase == name.downcase || sv_type['code'].downcase == name.downcase) && sv_type['creatable'] == true
|
|
2871
|
+
end
|
|
2872
|
+
if server_type.nil?
|
|
2873
|
+
print_red_alert "Server Type Not Selectable"
|
|
2874
|
+
end
|
|
2875
|
+
return server_type
|
|
2876
|
+
end
|
|
2877
|
+
|
|
2878
|
+
def cloud_type_for_id(id)
|
|
2879
|
+
cloud_types = @clouds_interface.cloud_types({max:1000})['zoneTypes']
|
|
2880
|
+
cloud_type = cloud_types.find { |z| z['id'].to_i == id.to_i}
|
|
2881
|
+
if cloud_type.nil?
|
|
2882
|
+
print_red_alert "Cloud Type not found by id #{id}"
|
|
2883
|
+
exit 1
|
|
2884
|
+
end
|
|
2885
|
+
return cloud_type
|
|
2886
|
+
end
|
|
2887
|
+
|
|
2888
|
+
def find_cluster_by_name_or_id(val)
|
|
2889
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
2890
|
+
find_cluster_by_id(val)
|
|
2891
|
+
else
|
|
2892
|
+
find_cluster_by_name(val)
|
|
2893
|
+
end
|
|
2894
|
+
end
|
|
2895
|
+
|
|
2896
|
+
def find_cluster_by_id(id)
|
|
2897
|
+
json_results = @clusters_interface.get(id.to_i)
|
|
2898
|
+
if json_results['cluster'].empty?
|
|
2899
|
+
print_red_alert "Cluster not found by id #{id}"
|
|
2900
|
+
exit 1
|
|
2901
|
+
end
|
|
2902
|
+
json_results['cluster']
|
|
2903
|
+
end
|
|
2904
|
+
|
|
2905
|
+
def find_cluster_by_name(name)
|
|
2906
|
+
json_results = @clusters_interface.list({name: name})
|
|
2907
|
+
if json_results['clusters'].empty? || json_results['clusters'].count > 1
|
|
2908
|
+
print_red_alert "Cluster not found by name #{name}"
|
|
2909
|
+
exit 1
|
|
2910
|
+
end
|
|
2911
|
+
json_results['clusters'][0]
|
|
2912
|
+
end
|
|
2913
|
+
|
|
2914
|
+
def format_server_power_state(server, return_color=cyan)
|
|
2915
|
+
out = ""
|
|
2916
|
+
if server['powerState'] == 'on'
|
|
2917
|
+
out << "#{green}ON#{return_color}"
|
|
2918
|
+
elsif server['powerState'] == 'off'
|
|
2919
|
+
out << "#{red}OFF#{return_color}"
|
|
2920
|
+
else
|
|
2921
|
+
out << "#{white}#{server['powerState'].to_s.upcase}#{return_color}"
|
|
2922
|
+
end
|
|
2923
|
+
out
|
|
2924
|
+
end
|
|
2925
|
+
|
|
2926
|
+
def format_server_status(server, return_color=cyan)
|
|
2927
|
+
out = ""
|
|
2928
|
+
status_string = server['status'].to_s.downcase
|
|
2929
|
+
if status_string == 'provisioned'
|
|
2930
|
+
out = "#{cyan}#{status_string.upcase}#{return_color}"
|
|
2931
|
+
elsif status_string == 'provisioning'
|
|
2932
|
+
out = "#{cyan}#{status_string.upcase}#{cyan}"
|
|
2933
|
+
elsif status_string == 'failed' or status_string == 'error'
|
|
2934
|
+
out = "#{red}#{status_string.upcase}#{return_color}"
|
|
2935
|
+
else
|
|
2936
|
+
out = "#{yellow}#{status_string.upcase}#{return_color}"
|
|
2937
|
+
end
|
|
2938
|
+
out
|
|
2939
|
+
end
|
|
2940
|
+
|
|
2941
|
+
def format_server_status_friendly(server, return_color=cyan)
|
|
2942
|
+
out = ""
|
|
2943
|
+
status_string = server['status'].to_s.downcase
|
|
2944
|
+
if status_string == 'provisioned'
|
|
2945
|
+
# out = format_server_power_state(server, return_color)
|
|
2946
|
+
# make it looks like format_instance_status
|
|
2947
|
+
if server['powerState'] == 'on'
|
|
2948
|
+
out << "#{green}RUNNING#{return_color}"
|
|
2949
|
+
elsif server['powerState'] == 'off'
|
|
2950
|
+
out << "#{red}STOPPED#{return_color}"
|
|
2951
|
+
else
|
|
2952
|
+
out << "#{white}#{server['powerState'].to_s.upcase}#{return_color}"
|
|
2953
|
+
end
|
|
2954
|
+
else
|
|
2955
|
+
out = format_server_status(server, return_color)
|
|
2956
|
+
end
|
|
2957
|
+
out
|
|
2958
|
+
end
|
|
2959
|
+
|
|
2960
|
+
def get_available_networks(host)
|
|
2961
|
+
results = @options_interface.options_for_source('availableNetworksForHost',{serverId: host['id'].to_i})
|
|
2962
|
+
available_networks = results['data'].collect {|it|
|
|
2963
|
+
{"id" => it["value"], "name" => it["name"], "value" => it["value"]}
|
|
2964
|
+
}
|
|
2965
|
+
return available_networks
|
|
2966
|
+
end
|
|
2967
|
+
|
|
2968
|
+
|
|
2969
|
+
def make_managed_option_types(connected=true)
|
|
2970
|
+
[
|
|
2971
|
+
#{'fieldName' => 'account', 'fieldLabel' => 'Account', 'type' => 'select', 'optionSource' => 'accounts', 'required' => true},
|
|
2972
|
+
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text'},
|
|
2973
|
+
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false},
|
|
2974
|
+
{'fieldName' => 'serverOs', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false},
|
|
2975
|
+
]
|
|
2976
|
+
end
|
|
2977
|
+
|
|
2978
|
+
def update_wiki_page_option_types
|
|
2979
|
+
[
|
|
2980
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'displayOrder' => 1, 'description' => 'The name of the wiki page for this instance. Default is the instance name.'},
|
|
2981
|
+
#{'fieldName' => 'category', 'fieldLabel' => 'Category', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
|
|
2982
|
+
{'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'textarea', 'required' => false, 'displayOrder' => 3, 'description' => 'The content (markdown) of the wiki page.'}
|
|
2983
|
+
]
|
|
2984
|
+
end
|
|
2985
|
+
|
|
2986
|
+
end
|