Skip to content

Commit

Permalink
[Platform] Need to fix install node exporter flow for onprem airgappe…
Browse files Browse the repository at this point in the history
…d/non passwordless sudo cases #5926

Summary:
If the onprem provider is airgapped or non-passwordless sudo, we ask the use to run universe provisioning before creating the universe. Therefore in this case, the install node_exporter toggle in the universe creation is useless.

Also fixed tooltip to show beside label instead of form input

Also added "advanced" toggle to onprem provider page to hide optional fields behind.

Test Plan: Test creating onprem provider + universe and ensure that the appropriate config values are passed along from provider to the universe being created.

Reviewers: wesley, arnav, sanketh, andrew

Reviewed By: andrew

Subscribers: jenkins-bot

Differential Revision: https://phabricator.dev.yugabyte.com/D9610
  • Loading branch information
daniel-yb committed Oct 13, 2020
1 parent f875819 commit 5723c22
Show file tree
Hide file tree
Showing 29 changed files with 361 additions and 167 deletions.
5 changes: 4 additions & 1 deletion managed/devops/opscli/ybops/cloud/common/method.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ def add_extra_args(self):
help="Path to local directory with the prometheus tarball.")
self.parser.add_argument("--node_exporter_port", type=int, default=9300,
help="The port for node_exporter to bind to")
self.parser.add_argument("--install_node_exporter", default=True)
self.parser.add_argument("--node_exporter_user", default="prometheus")
self.parser.add_argument("--install_node_exporter", action="store_true")

def callback(self, args):
host_info = self.cloud.get_host_info(args)
Expand All @@ -381,6 +382,8 @@ def callback(self, args):
self.extra_vars.update({"node_exporter_port": args.node_exporter_port})
if args.install_node_exporter:
self.extra_vars.update({"install_node_exporter": args.install_node_exporter})
if args.node_exporter_user:
self.extra_vars.update({"node_exporter_user": args.node_exporter_user})
self.extra_vars.update({"instance_type": args.instance_type})
self.extra_vars["device_names"] = self.cloud.get_device_names(args)
self.cloud.setup_ansible(args).run("yb-server-provision.yml", self.extra_vars, host_info)
Expand Down
4 changes: 4 additions & 0 deletions managed/devops/opscli/ybops/cloud/onprem/method.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ def add_extra_args(self):
help='If the ssh_user has passwordless sudo access or not.')
self.parser.add_argument("--air_gap", action="store_true",
help='If instances are air gapped or not.')
self.parser.add_argument("--node_exporter_port", type=int, default=9300,
help="The port for node_exporter to bind to")
self.parser.add_argument("--node_exporter_user", default="prometheus")
self.parser.add_argument("--install_node_exporter", action="store_true")

def callback(self, args):
config = {'devops_home': ybutils.YB_DEVOPS_HOME, 'cloud': self.cloud.name}
Expand Down
7 changes: 7 additions & 0 deletions managed/devops/opscli/ybops/data/provision_instance.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ def construct_command(args):
{%- if air_gap %}
'--air_gap ' \
{%- endif %}
{%- if install_node_exporter %}
'--install_node_exporter ' \
'--node_exporter_user ' \
'{{ node_exporter_user }} ' \
'--node_exporter_port ' \
'{{ node_exporter_port }} ' \
{%- endif %}
'--local_package_path {{local_package_path}} '\
'@@DEFAULT_NODE_NAME@@' % (args.ip, args.mount_points)

Expand Down
21 changes: 21 additions & 0 deletions managed/devops/roles/get_prometheus_user_group/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2020 YugaByte, Inc. and Contributors
#
# Licensed under the Polyform Free Trial License 1.0.0 (the "License"); you
# may not use this file except in compliance with the License. You
# may obtain a copy of the License at
#
# https://github.com/YugaByte/yugabyte-db/blob/master/licenses/POLYFORM-FREE-TRIAL-LICENSE-1.0.0.txt

- name: Get the primary group if user already exists
shell: "id -gn {{ node_exporter_user }}"
register: user_group
ignore_errors: True
failed_when: False

- set_fact:
node_exporter_group: "prometheus"
when: user_group.rc != 0

- set_fact:
node_exporter_group: "{{ user_group.stdout }}"
when: user_group.rc == 0
8 changes: 4 additions & 4 deletions managed/devops/roles/provision-cluster-server/meta/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ dependencies:
- role: mount_ephemeral_drives
when: cloud_type != "onprem"

- role: swamper
prometheus_components:
- node_exporter

- role: create_user
create_user:
name: "{{ user_name }}"
Expand All @@ -30,6 +26,10 @@ dependencies:
sudo_user: "{{ yb_server_ssh_user | default(omit) }}"
authorized_keys: "{{ cluster_server_vault | get_value('authorized_keys') }}"

- role: swamper
prometheus_components:
- node_exporter

- role: install_backup_util
util:
name: "azcopy"
Expand Down
6 changes: 6 additions & 0 deletions managed/devops/roles/swamper/meta/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
# https://github.com/YugaByte/yugabyte-db/blob/master/licenses/POLYFORM-FREE-TRIAL-LICENSE-1.0.0.txt

dependencies:
- role: get_prometheus_user_group
become: yes
become_method: sudo

- role: ansible-prometheus
become: yes
become_method: sudo
prometheus_go_version: 1.7
prometheus_use_service: true
prometheus_node_exporter_opts: "-web.listen-address=:{{ node_exporter_port }}"
prometheus_node_exporter_use_systemd: true
prometheus_user: "{{ node_exporter_user }}"
prometheus_group: "{{ node_exporter_group }}"
when: install_node_exporter is not defined or install_node_exporter|bool
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,8 @@ public SubTaskGroup createSetupServerTasks(Collection<NodeDetails> nodes) {
// Whether to install node_exporter on nodes or not.
params.extraDependencies.installNodeExporter =
taskParams().extraDependencies.installNodeExporter;
// Which user the node exporter service will run as
params.nodeExporterUser = taskParams().nodeExporterUser;

// Create the Ansible task to setup the server.
AnsibleSetupServer ansibleSetupServer = new AnsibleSetupServer();
Expand Down
21 changes: 12 additions & 9 deletions managed/src/main/java/com/yugabyte/yw/common/NodeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,18 @@ private List<String> getAccessKeySpecificCommand(NodeTaskParams params, NodeComm
subCommand.add(keyInfo.sshUser);
}

if (params instanceof AnsibleSetupServer.Params &&
accessKey.getKeyInfo().airGapInstall) {
subCommand.add("--air_gap");
if (params instanceof AnsibleSetupServer.Params) {
if (keyInfo.airGapInstall) {
subCommand.add("--air_gap");
}

if (keyInfo.installNodeExporter) {
subCommand.add("--install_node_exporter");
subCommand.add("--node_exporter_port");
subCommand.add(Integer.toString(keyInfo.nodeExporterPort));
subCommand.add("--node_exporter_user");
subCommand.add(keyInfo.nodeExporterUser);
}
}
}

Expand Down Expand Up @@ -437,12 +446,6 @@ public ShellProcessHandler.ShellResponse nodeCommand(NodeCommandType type,
}
}

commandArgs.add("--node_exporter_port");
commandArgs.add(Integer.toString(taskParam.communicationPorts.nodeExporterPort));

commandArgs.add("--install_node_exporter");
commandArgs.add(Boolean.toString(taskParam.extraDependencies.installNodeExporter));

if (cloudType.equals(Common.CloudType.aws)) {
if (taskParam.useTimeSync) {
commandArgs.add("--use_chrony");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ private String getOrCreateProvisionFilePath(UUID providerUUID) {
throw new RuntimeException("Unable to create provision file path " + provisionFilePath.getAbsolutePath());
}

public void createProvisionTemplate(AccessKey accessKey, boolean airGapInstall, boolean passwordlessSudoAccess) {
public void createProvisionTemplate(
AccessKey accessKey,
boolean airGapInstall,
boolean passwordlessSudoAccess,
boolean installNodeExporter,
Integer nodeExporterPort,
String nodeExporterUser
) {
AccessKey.KeyInfo keyInfo = accessKey.getKeyInfo();
String path = getOrCreateProvisionFilePath(accessKey.getProviderUUID());

Expand All @@ -61,19 +68,32 @@ public void createProvisionTemplate(AccessKey accessKey, boolean airGapInstall,
commandArgs.add(appConfig.getString("yb.thirdparty.packagePath"));
commandArgs.add("--custom_ssh_port");
commandArgs.add(keyInfo.sshPort.toString());

if (airGapInstall) {
commandArgs.add("--air_gap");
}

if (passwordlessSudoAccess) {
commandArgs.add("--passwordless_sudo");
}

if (installNodeExporter) {
commandArgs.add("--install_node_exporter");
commandArgs.add("--node_exporter_port");
commandArgs.add(nodeExporterPort.toString());
commandArgs.add("--node_exporter_user");
commandArgs.add(nodeExporterUser);
}

JsonNode result = execAndParseCommandCloud(accessKey.getProviderUUID(), "template", commandArgs);

if (result.get("error") == null) {
keyInfo.passwordlessSudoAccess = passwordlessSudoAccess;
keyInfo.provisionInstanceScript = path + "/" + PROVISION_SCRIPT;
keyInfo.airGapInstall = airGapInstall;
keyInfo.installNodeExporter = installNodeExporter;
keyInfo.nodeExporterPort = nodeExporterPort;
keyInfo.nodeExporterUser = nodeExporterUser;
accessKey.setKeyInfo(keyInfo);
accessKey.save();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,13 @@ public Result create(UUID customerUUID, UUID providerUUID) {
// and create a preprovision script
if (region.provider.code.equals(onprem.name())) {
templateManager.createProvisionTemplate(
accessKey,
airGapInstall,
formData.get().passwordlessSudoAccess);
accessKey,
airGapInstall,
formData.get().passwordlessSudoAccess,
formData.get().installNodeExporter,
formData.get().nodeExporterPort,
formData.get().nodeExporterUser
);
}
} catch(RuntimeException | IOException e) {
LOG.error(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.yugabyte.yw.common.kms.EncryptionAtRestManager;
import com.yugabyte.yw.common.PlacementInfoUtil;
import com.yugabyte.yw.common.Util;
import com.yugabyte.yw.models.AccessKey;
import com.yugabyte.yw.models.Audit;
import com.yugabyte.yw.models.CertificateInfo;
import com.yugabyte.yw.models.Customer;
Expand Down Expand Up @@ -450,12 +451,32 @@ public Result create(UUID customerUUID) {
for (Cluster c : taskParams.clusters) {
Provider provider = Provider.find.byId(UUID.fromString(c.userIntent.provider));
c.userIntent.providerType = CloudType.valueOf(provider.code);
if (
c.userIntent.providerType.equals(CloudType.onprem) &&
provider.getConfig().containsKey("USE_HOSTNAME")
) {
c.userIntent.useHostname = Boolean.parseBoolean(provider.getConfig().get("USE_HOSTNAME"));
if (c.userIntent.providerType.equals(CloudType.onprem)) {
if (provider.getConfig().containsKey("USE_HOSTNAME")) {
c.userIntent.useHostname =
Boolean.parseBoolean(provider.getConfig().get("USE_HOSTNAME"));
}
}

// Set the node exporter config based on the provider
if (!c.userIntent.providerType.equals(CloudType.kubernetes)) {
AccessKey accessKey = AccessKey.get(provider.uuid, c.userIntent.accessKeyCode);
AccessKey.KeyInfo keyInfo = accessKey.getKeyInfo();
boolean installNodeExporter = keyInfo.installNodeExporter;
int nodeExporterPort = keyInfo.nodeExporterPort;
String nodeExporterUser = keyInfo.nodeExporterUser;
taskParams.extraDependencies.installNodeExporter = installNodeExporter;
taskParams.communicationPorts.nodeExporterPort = nodeExporterPort;

for (NodeDetails node : taskParams.nodeDetailsSet) {
node.nodeExporterPort = nodeExporterPort;
}

if (installNodeExporter) {
taskParams.nodeExporterUser = nodeExporterUser;
}
}

updatePlacementInfo(taskParams.getNodesInCluster(c.uuid), c.placementInfo);
}

Expand Down Expand Up @@ -651,7 +672,7 @@ public Result update(UUID customerUUID, UUID universeUUID) {
Customer customer = Customer.get(customerUUID);

UniverseDefinitionTaskParams taskParams;
ObjectNode formData = null;
ObjectNode formData;
try {
LOG.info("Update {} for {}.", customerUUID, universeUUID);
// Get the user submitted form data.
Expand All @@ -676,8 +697,8 @@ public Result update(UUID customerUUID, UUID universeUUID) {

try {
Cluster primaryCluster = taskParams.getPrimaryCluster();
UUID uuid = null;
PlacementInfo placementInfo = null;
UUID uuid;
PlacementInfo placementInfo;
TaskType taskType = TaskType.EditUniverse;
if (primaryCluster == null) {
// Update of a read only cluster.
Expand All @@ -704,6 +725,22 @@ public Result update(UUID customerUUID, UUID universeUUID) {
"Manually migrate the deployment to helm3 " +
"and then mark the universe as helm 3 compatible.");
}
} else {
// Set the node exporter config based on the provider
UniverseDefinitionTaskParams universeDetails = universe.getUniverseDetails();
boolean installNodeExporter = universeDetails.extraDependencies.installNodeExporter;
int nodeExporterPort = universeDetails.communicationPorts.nodeExporterPort;
String nodeExporterUser = universeDetails.nodeExporterUser;
taskParams.extraDependencies.installNodeExporter = installNodeExporter;
taskParams.communicationPorts.nodeExporterPort = nodeExporterPort;

for (NodeDetails node : taskParams.nodeDetailsSet) {
node.nodeExporterPort = nodeExporterPort;
}

if (installNodeExporter) {
taskParams.nodeExporterUser = nodeExporterUser;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@ public class AccessKeyFormData {
public boolean passwordlessSudoAccess = true;

public boolean airGapInstall = false;

public boolean installNodeExporter = true;

public String nodeExporterUser = "prometheus";

public Integer nodeExporterPort = 9300;
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ public static class ExtraDependencies {
public boolean installNodeExporter = true;
}

// Which user to run the node exporter service on nodes with
public String nodeExporterUser = "prometheus";

// The primary device info.
public DeviceInfo deviceInfo;

Expand Down
3 changes: 3 additions & 0 deletions managed/src/main/java/com/yugabyte/yw/models/AccessKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public static class KeyInfo {
public boolean airGapInstall = false;
public boolean passwordlessSudoAccess = true;
public String provisionInstanceScript = "";
public boolean installNodeExporter = true;
public Integer nodeExporterPort = 9300;
public String nodeExporterUser = "prometheus";
}

@EmbeddedId
Expand Down
21 changes: 5 additions & 16 deletions managed/src/test/java/com/yugabyte/yw/common/NodeManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,6 @@ private List<String> nodeCommand(
}
}

expectedCommand.add("--node_exporter_port");
expectedCommand.add("9300");
expectedCommand.add("--install_node_exporter");
expectedCommand.add("true");

break;
case Configure:
AnsibleConfigureServers.Params configureParams = (AnsibleConfigureServers.Params) params;
Expand Down Expand Up @@ -577,17 +572,6 @@ public void testProvisionWithAWSTags() {
t
));

if (t.cloudType.equals(Common.CloudType.aws)) {
expectedCommandArrayList.add(15, "--node_exporter_port");
expectedCommandArrayList.add(16, "9300");
expectedCommandArrayList.add(17, "--install_node_exporter");
expectedCommandArrayList.add(18, "true");
expectedCommandArrayList.remove(24);
expectedCommandArrayList.remove(23);
expectedCommandArrayList.remove(22);
expectedCommandArrayList.remove(21);
}

nodeManager.nodeCommand(NodeManager.NodeCommandType.Provision, params);
verify(shellProcessHandler, times(1))
.run(expectedCommandArrayList, t.region.provider.getConfig());
Expand Down Expand Up @@ -652,6 +636,11 @@ private void runAndTestProvisionWithAccessKeyAndSG(String sgId) {
accessKeyCommands.add("--custom_ssh_port");
accessKeyCommands.add("3333");
accessKeyCommands.add("--air_gap");
accessKeyCommands.add("--install_node_exporter");
accessKeyCommands.add("--node_exporter_port");
accessKeyCommands.add("9300");
accessKeyCommands.add("--node_exporter_user");
accessKeyCommands.add("prometheus");
expectedCommand.addAll(expectedCommand.size() - accessKeyIndexOffset, accessKeyCommands);

nodeManager.nodeCommand(NodeManager.NodeCommandType.Provision, params);
Expand Down
Loading

0 comments on commit 5723c22

Please sign in to comment.