Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Public Cloud instance public IP when needed #21141

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions lib/publiccloud/azure.pm
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ sub upload_boot_diagnostics {
my $time = $dt->hms;
my $bootlog_name = "/tmp/bootlog-$time.txt";

my $cmd_enable = "az vm boot-diagnostics enable --ids $instance_id";
my $cmd_enable = "az vm boot-diagnostics enable --ids $instance_id --resource-group $resource_group";
my $out = script_output($cmd_enable, 60 * 5, proceed_on_failure => 1);
record_info('INFO', $cmd_enable . $/ . $out);

Expand Down Expand Up @@ -573,12 +573,14 @@ sub get_state_from_instance
return $1;
}

sub get_ip_from_instance
{
my ($self, $instance) = @_;
my $id = $instance->instance_id();
sub get_public_ip {
my ($self) = @_;

my $instance_id = $self->get_terraform_output('.instance_id.value[0]');
$instance_id =~ s/.*\/(.*)/$1/;
my $resource_group = $self->get_terraform_output('.resource_group_name.value[0]');

my $out = decode_azure_json(script_output("az vm list-ip-addresses --ids '$id'", quiet => 1));
my $out = decode_azure_json(script_output("az vm list-ip-addresses --name '$instance_id' --resource-group '$resource_group'", quiet => 1));
return $out->[0]->{virtualMachine}->{network}->{publicIpAddresses}->[0]->{ipAddress};
}

Expand All @@ -589,9 +591,10 @@ sub stop_instance
# which is equal to the resource group
# TODO maybe we need to change the azure.tf file to retrieve the id instead of the name
my $id = $instance->instance_id();
my $resource_group = $instance->resource_group();
my $attempts = 60;

die('Outdated instance object') if ($self->get_ip_from_instance($instance) ne $instance->public_ip);
die('Outdated instance object') if ($self->get_public_ip() ne $instance->public_ip);

assert_script_run("az vm stop --ids '$id'", quiet => 1);
while ($self->get_state_from_instance($instance) ne 'stopped' && $attempts-- > 0) {
Expand All @@ -604,11 +607,12 @@ sub start_instance
{
my ($self, $instance, %args) = @_;
my $id = $instance->instance_id();
my $resource_group = $instance->resource_group();

die("Try to start a running instance") if ($self->get_state_from_instance($instance) ne 'stopped');

assert_script_run("az vm start --ids '$id'", quiet => 1);
$instance->public_ip($self->get_ip_from_instance($instance));
$instance->public_ip($self->get_public_ip());
}

=head2
Expand Down Expand Up @@ -643,6 +647,8 @@ sub cleanup {
record_info('INSTANCE_ID', $instance_id);
my $resource_group = $self->get_terraform_output('.resource_group_name.value[0]');
record_info('RESOURCE_GROUP', $resource_group);
my $public_ip = $self->get_public_ip();
record_info('PUBLIC_IP', $public_ip);
script_run('cd');

select_host_console(force => 1);
Expand Down
37 changes: 19 additions & 18 deletions lib/publiccloud/ec2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ sub cleanup {

script_run('cd ' . get_var('PUBLIC_CLOUD_TERRAFORM_DIR', '~/terraform'));
my $instance_id = $self->get_terraform_output('.vm_name.value[]');
record_info('INSTANCE_ID', $instance_id);
my $public_ip = $self->get_public_ip();
record_info('PUBLIC_IP', $public_ip);
script_run('cd');

if (!check_var('PUBLIC_CLOUD_SLES4SAP', 1) && defined($instance_id)) {
Expand All @@ -253,24 +256,23 @@ sub cleanup {
$self->delete_keypair();
}

sub describe_instance
{
my ($self, $instance) = @_;
my $json_output = decode_json(script_output('aws ec2 describe-instances --filter Name=instance-id,Values=' . $instance->instance_id(), quiet => 1));
sub describe_instance {
my ($self, $instance_id) = @_;
my $json_output = decode_json(script_output('aws ec2 describe-instances --filter Name=instance-id,Values=' . $instance_id, quiet => 1));
my $i_desc = $json_output->{Reservations}->[0]->{Instances}->[0];
return $i_desc;
}

sub get_state_from_instance
{
sub get_state_from_instance {
my ($self, $instance) = @_;
return $self->describe_instance($instance)->{State}->{Name};
my $instance_id = $instance->instance_id();
return $self->describe_instance($instance_id)->{State}->{Name};
}

sub get_ip_from_instance
{
my ($self, $instance) = @_;
return $self->describe_instance($instance)->{PublicIpAddress};
sub get_public_ip {
my ($self) = @_;
my $instance_id = $self->get_terraform_output('.vm_name.value[]');
return $self->describe_instance($instance_id)->{PublicIpAddress};
}

sub stop_instance
Expand All @@ -279,7 +281,7 @@ sub stop_instance
my $instance_id = $instance->instance_id();
my $attempts = 60;

die("Outdated instance object") if ($instance->public_ip ne $self->get_ip_from_instance($instance));
die("Outdated instance object") if ($instance->public_ip ne $self->get_public_ip());

assert_script_run('aws ec2 stop-instances --instance-ids ' . $instance_id, quiet => 1);

Expand All @@ -295,26 +297,25 @@ sub start_instance
my $attempts = 60;
my $instance_id = $instance->instance_id();

my $i_desc = $self->describe_instance($instance);
my $i_desc = $self->describe_instance($instance_id);
die("Try to start a running instance") if ($i_desc->{State}->{Name} ne 'stopped');

assert_script_run("aws ec2 start-instances --instance-ids $instance_id", quiet => 1);
sleep 1; # give some time to update public_ip
my $public_ip;
while (!defined($public_ip) && $attempts-- > 0) {
$public_ip = $self->get_ip_from_instance($instance);
$public_ip = $self->get_public_ip();
}
die("Unable to get new public IP") unless ($public_ip);
$instance->public_ip($public_ip);
}

sub change_instance_type
{
sub change_instance_type {
my ($self, $instance, $instance_type) = @_;
die "Instance type is already $instance_type" if ($self->describe_instance($instance)->{InstanceType} eq $instance_type);
my $instance_id = $instance->instance_id();
die "Instance type is already $instance_type" if ($self->describe_instance($instance_id)->{InstanceType} eq $instance_type);
assert_script_run("aws ec2 modify-instance-attribute --instance-id $instance_id --instance-type '{\"Value\": \"$instance_type\"}'");
die "Failed to change instance type to $instance_type" if ($self->describe_instance($instance)->{InstanceType} ne $instance_type);
die "Failed to change instance type to $instance_type" if ($self->describe_instance($instance_id)->{InstanceType} ne $instance_type);
}

sub query_metadata {
Expand Down
48 changes: 24 additions & 24 deletions lib/publiccloud/gce.pm
Original file line number Diff line number Diff line change
Expand Up @@ -125,79 +125,79 @@ sub get_image_id {
return $image;
}

sub describe_instance
{
my ($self, $instance) = @_;
my $name = $instance->instance_id();
sub describe_instance {
my ($self, $instance_id) = @_;
my $attempts = 10;

my $out = [];
while (@{$out} == 0 && $attempts-- > 0) {
$out = decode_json(script_output("gcloud compute instances list --filter=\"name=( 'NAME' '$name')\" --format json", quiet => 1));
$out = decode_json(script_output("gcloud compute instances list --filter=\"name=( 'NAME' '$instance_id')\" --format json", quiet => 1));
sleep 3;
}

die("Unable to retrive description of instance $name") unless ($attempts > 0);
die("Unable to retrive description of instance $instance_id") unless ($attempts > 0);
return $out->[0];
}

sub get_state_from_instance
{
my ($self, $instance) = @_;
my $name = $instance->instance_id();
my $instance_id = $instance->instance_id();

my $desc = $self->describe_instance($instance);
my $desc = $self->describe_instance($instance_id);
die("Unable to get status") unless exists($desc->{status});
return $desc->{status};
}

sub get_ip_from_instance
{
my ($self, $instance) = @_;
my $name = $instance->instance_id();
sub get_public_ip {
my ($self) = @_;
my $instance_id = $self->get_terraform_output(".vm_name.value[0]");

my $desc = $self->describe_instance($instance);
my $desc = $self->describe_instance($instance_id);
die("Unable to get public_ip") unless exists($desc->{networkInterfaces}->[0]->{accessConfigs}->[0]->{natIP});
return $desc->{networkInterfaces}->[0]->{accessConfigs}->[0]->{natIP};
}

sub stop_instance
{
sub stop_instance {
my ($self, $instance) = @_;
my $name = $instance->instance_id();
my $instance_id = $instance->instance_id();
my $attempts = 60;

die('Outdated instance object') if ($self->get_ip_from_instance($instance) ne $instance->public_ip);
die('Outdated instance object') if ($self->get_public_ip() ne $instance->public_ip);

assert_script_run("gcloud compute instances stop $name --async", quiet => 1);
assert_script_run("gcloud compute instances stop $instance_id --async", quiet => 1);
while ($self->get_state_from_instance($instance) ne 'TERMINATED' && $attempts-- > 0) {
sleep 5;
}
die("Failed to stop instance $name") unless ($attempts > 0);
die("Failed to stop instance $instance_id") unless ($attempts > 0);
}

sub start_instance
{
sub start_instance {
my ($self, $instance, %args) = @_;
my $name = $instance->instance_id();
my $instance_id = $instance->instance_id();
my $attempts = 60;

die("Try to start a running instance") if ($self->get_state_from_instance($instance) ne 'TERMINATED');

assert_script_run("gcloud compute instances start $name --async", quiet => 1);
assert_script_run("gcloud compute instances start $instance_id --async", quiet => 1);
while ($self->get_state_from_instance($instance) eq 'TERMINATED' && $attempts-- > 0) {
sleep 1;
}
$instance->public_ip($self->get_ip_from_instance($instance));
$instance->public_ip($self->get_public_ip());
}

sub cleanup {
my ($self, $args) = @_;
select_host_console(force => 1);

my $region = $self->{provider_client}->{region};
record_info('REGION', $region);
my $project = $self->{provider_client}->{project_id};
record_info('PROJECT', $project);
my $instance_id = $self->get_terraform_output(".vm_name.value[0]");
record_info('INSTANCE_ID', $instance_id);
my $public_ip = $self->get_public_ip();
record_info('PUBLIC_IP', $public_ip);
# gce provides full serial log, so extended timeout
if (!check_var('PUBLIC_CLOUD_SLES4SAP', 1) && defined($instance_id)) {
if ($instance_id =~ /$self->{resource_name}/) {
Expand Down
26 changes: 22 additions & 4 deletions lib/publiccloud/instance.pm
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,14 @@ sub wait_for_ssh {
$exit_code = script_run('nc -vz -w 1 ' . $self->{public_ip} . ' 22', quiet => 1);
last if (isok($exit_code) and not $args{wait_stop}); # ssh port open ok
last if (not isok($exit_code) and $args{wait_stop}); # ssh port closed ok

if ($duration >= $args{timeout} - 30) {
my $public_ip_from_provider = $self->provider->get_public_ip();
if ($args{public_ip} eq $public_ip_from_provider) {
record_info('IP CHANGED', printf("The address we know is %s but provider returns %s", $args{public_ip}, $public_ip_from_provider));
}
}

sleep $delay;
} # endloop

Expand Down Expand Up @@ -616,15 +624,25 @@ Test the network speed.

sub network_speed_test() {
my ($self, %args) = @_;
my ($cmd, $ret);

# Curl stats output format
my $write_out
= 'time_namelookup:\t%{time_namelookup} s\ntime_connect:\t\t%{time_connect} s\ntime_appconnect:\t%{time_appconnect} s\ntime_pretransfer:\t%{time_pretransfer} s\ntime_redirect:\t\t%{time_redirect} s\ntime_starttransfer:\t%{time_starttransfer} s\ntime_total:\t\t%{time_total} s\n';
# PC RMT server domain name
my $rmt_host = "smt-" . lc(get_required_var('PUBLIC_CLOUD_PROVIDER')) . ".susecloud.net";
my $rmt = $self->run_ssh_command(cmd => "grep \"$rmt_host\" /etc/hosts", proceed_on_failure => 1);
record_info("rmt_host", $rmt);
record_info("ping 1.1.1.1", $self->run_ssh_command(cmd => "ping -c30 1.1.1.1", proceed_on_failure => 1, timeout => 600));
record_info("curl $rmt_host", $self->run_ssh_command(cmd => "curl -w '$write_out' -o /dev/null -v https://$rmt_host/", proceed_on_failure => 1));

$cmd = "grep \"$rmt_host\" /etc/hosts";
$ret = $self->run_ssh_command(cmd => $cmd, proceed_on_failure => 1);
record_info("RMT_HOST", printf('$ %s\n%s', $cmd, $ret));

$cmd = "ping -c3 1.1.1.1";
$ret = $self->run_ssh_command(cmd => $cmd, proceed_on_failure => 1);
record_info("PING", printf('$ %s\n%s', $cmd, $ret));

$cmd = "curl -w '$write_out' -o /dev/null -v https://$rmt_host/";
$ret = $self->run_ssh_command(cmd => $cmd, proceed_on_failure => 1);
record_info("CURL", printf('$ %s\n%s', $cmd, $ret));
}

sub cleanup_cloudinit() {
Expand Down
4 changes: 3 additions & 1 deletion lib/publiccloud/provider.pm
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ sub terraform_apply {
# 4) Terraform output

my $output = decode_json(script_output("terraform output -json"));
my ($vms, $ips, $resource_id);
my ($vms, $ips, $resource_group, $resource_id);
if (get_var('PUBLIC_CLOUD_SLES4SAP')) {
foreach my $vm_type ('hana', 'drbd', 'netweaver') {
push @{$vms}, @{$output->{$vm_type . '_name'}->{value}};
Expand All @@ -610,6 +610,7 @@ sub terraform_apply {
} else {
$vms = $output->{vm_name}->{value};
$ips = $output->{public_ip}->{value};
$resource_group = $output->{resource_group_name}->{value};
# ResourceID is only provided in the PUBLIC_CLOUD_AZURE_NFS_TEST
$resource_id = $output->{resource_id}->{value} if (get_var('PUBLIC_CLOUD_AZURE_NFS_TEST'));
}
Expand All @@ -618,6 +619,7 @@ sub terraform_apply {
foreach my $i (0 .. $#{$vms}) {
my $instance = publiccloud::instance->new(
public_ip => @{$ips}[$i],
resource_group => $resource_group,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but resource group is relevant only for Azure and this code is used by all 3 providers 🤔

resource_id => $resource_id,
instance_id => @{$vms}[$i],
username => $self->provider_client->username,
Expand Down