From 1d61c8fff729f1984a238a702cef9e0a2b6c9e4c Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 16 Jul 2021 14:29:49 -0400 Subject: [PATCH] fix(cgi-bin): modify manage_vnc_pipes endpoint to trigger a job --- Anvil/Tools.pm | 1 + cgi-bin/manage_vnc_pipes | 921 +-------------------------------------- share/words.xml | 2 + 3 files changed, 26 insertions(+), 898 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 02d4ee28..e90a9d75 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -1221,6 +1221,7 @@ sub _set_paths 'striker-initialize-host' => "/usr/sbin/striker-initialize-host", 'striker-manage-install-target' => "/usr/sbin/striker-manage-install-target", 'striker-manage-peers' => "/usr/sbin/striker-manage-peers", + 'striker-manage-vnc-pipes' => "/usr/sbin/striker-manage-vnc-pipes", 'striker-open-ssh-tunnel' => "/usr/sbin/striker-open-ssh-tunnel", 'striker-parse-oui' => "/usr/sbin/striker-parse-oui", 'striker-prep-database' => "/usr/sbin/striker-prep-database", diff --git a/cgi-bin/manage_vnc_pipes b/cgi-bin/manage_vnc_pipes index 4ce47344..c9f36c24 100755 --- a/cgi-bin/manage_vnc_pipes +++ b/cgi-bin/manage_vnc_pipes @@ -22,910 +22,32 @@ my $anvil = Anvil::Tools->new(); $anvil->Log->level({ set => 2 }); -sub get_server_info +sub get_vnc_pipe_info { my $parameters = shift; my $server_uuid = $parameters->{server_uuid}; - my $server_info; - - my $query = " -SELECT - ser.server_name, hos.host_name, hos.host_uuid -FROM - public.servers AS ser -JOIN - public.hosts AS hos -ON - ser.server_host_uuid = hos.host_uuid -WHERE - server_uuid = ".$anvil->Database->quote($server_uuid)." -;"; - my $results = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ }); - my $count = @{$results}; - - if ($count == 1) - { - my $row = $results->[0]; - - $server_info = {}; - $server_info->{server_name} = $row->[0]; - $server_info->{host_name} = $row->[1]; - $server_info->{host_uuid} = $row->[2]; - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - server_name => $server_info->{server_name}, - host_name => $server_info->{host_name}, - host_uuid => $server_info->{host_uuid} - } }); - } - - return $server_info; -} - -sub get_vnc_info -{ - my $parameters = shift; - my $host_name = $parameters->{host_name}; - my $server_name = $parameters->{server_name}; - my $port_base = 5900; - # Requires root to access VM information. - my $shell_call = "virsh vncdisplay ".$server_name; - my $vnc_info; - - my ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call({ - target => $host_name, - remote_user => "root", - shell_call => $shell_call, - 'close' => 1 - }); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - - if ($shell_return_code == 0) - { - my ($port_offset) = $shell_output =~ /:(\d+)$/; - - $vnc_info = { host_name => $host_name }; - $vnc_info->{port} = $port_base + int($port_offset); - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - port_offset => $port_offset, - vnc_port => $vnc_info->{port} - } }); - } - - return $vnc_info; -} - -sub is_websockify_process -{ - my $parameters = shift; - my $host_name = $parameters->{host_name}; - my $ws_pid = $parameters->{ws_pid}; - my $shell_call = "ps -e -o command -h -p ".$ws_pid; - - my ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call({ - target => $host_name, - remote_user => "admin", - shell_call => $shell_call, - 'close' => 1 - }); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - - return $shell_output =~ /websockify/ ? 1 : 0; -} - -sub is_ssh_process -{ - my $parameters = shift; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - my $shell_call = "ps -e -o command -h -p ".$ssh_tunnel_pid; - - my ($shell_output, $shell_return_code) = $anvil->System->call({ shell_call => $shell_call }); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_return_code => $shell_return_code - } }); - - return $shell_output =~ /striker-open-ssh-tunnel/ ? 1 : 0; -} - -sub is_websockify_exists -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_uuid = $parameters->{host_uuid}; - my $server_vnc_port = $parameters->{server_vnc_port}; - - my $query = " -SELECT - vnc.server_vnc_port, hos.host_name, hos.host_uuid, vnc.ws_pid, vnc.ws_source_port -FROM - public.vnc_pipes AS vnc -JOIN - public.hosts AS hos -ON - vnc.ws_host_uuid = hos.host_uuid -WHERE - vnc.server_uuid = ".$anvil->Database->quote($server_uuid)." -;"; - - my $results = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ }); - my $count = @{$results}; - my $ws_exists_info = { exists_code => 0 }; - - if ($count > 0) - { - my $row = $results->[0]; - my $server_vnc_port_in_record = $row->[0]; - my $host_name = $row->[1]; - my $host_uuid_in_record = $row->[2]; - my $ws_pid = $row->[3]; - my $ws_source_port = $row->[4]; - my $clean_up_parameters = { host_name => $host_name, ws_pid => $ws_pid }; - - $ws_exists_info->{ws_pid} = $ws_pid; - $ws_exists_info->{ws_source_port} = $ws_source_port; - $ws_exists_info->{exists_code} = 1; - - if ($host_uuid ne $host_uuid_in_record) - { - # VNC server host mismatch; try to stop the recorded instance. - # Likely happens after a server migration. - stop_websockify($clean_up_parameters); - - # No need to preserve the websockify source port in - # this case because the tunnel will need to be replaced - # as well. - delete $ws_exists_info->{ws_source_port}; - - return $ws_exists_info; - } - - if ($server_vnc_port != $server_vnc_port_in_record) - { - # VNC server port mismatch; try to stop the recorded instance. - stop_websockify($clean_up_parameters); - - return $ws_exists_info; - } - - if (not is_websockify_process($clean_up_parameters)) - { - # The recorded instance died. - return $ws_exists_info; - } - - # Passed all tests; process considered exists. - $ws_exists_info->{exists_code} = 2; - } - - return $ws_exists_info; -} - -sub is_ssh_tunnel_exists -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $ssh_tunnel_host_uuid = $parameters->{ssh_tunnel_host_uuid}; - my $ws_host_uuid = $parameters->{ws_host_uuid}; - my $ws_source_port = $parameters->{ws_source_port}; - - my $query = " -SELECT - ws_host_uuid, ws_source_port, ssh_tunnel_pid, ssh_tunnel_forward_port -FROM - public.vnc_pipes -WHERE - server_uuid = ".$anvil->Database->quote($server_uuid)." -AND - ssh_tunnel_host_uuid = ".$anvil->Database->quote($ssh_tunnel_host_uuid)." -;"; - - my $results = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ }); - my $count = @{$results}; - my $ssh_tunnel_exists_info = { exists_code => 0 }; - - if ($count == 1) - { - my $row = $results->[0]; - my $ws_host_uuid_in_record = $row->[0]; - my $ws_source_port_in_record = $row->[1]; - my $ssh_tunnel_pid = $row->[2]; - my $ssh_tunnel_forward_port = $row->[3]; - my $clean_up_parameters = { ssh_tunnel_pid => $ssh_tunnel_pid }; - - $ssh_tunnel_exists_info->{ssh_tunnel_pid} = $ssh_tunnel_pid; - $ssh_tunnel_exists_info->{ssh_tunnel_forward_port} = $ssh_tunnel_forward_port; - $ssh_tunnel_exists_info->{exists_code} = 1; - - if ($ws_host_uuid ne $ws_host_uuid_in_record) - { - # Websockify host mismatch; try to stop the recorded instance. - # Likely happens after a server migration. - stop_ssh_tunnel($clean_up_parameters); - - # No need to preserve the SSH tunnel forward port in - # this case because the websockify instance will need - # to be replaced as well. - delete $ssh_tunnel_exists_info->{ssh_tunnel_forward_port}; - - return $ssh_tunnel_exists_info; - } - - if ($ws_source_port != $ws_source_port_in_record) - { - # Websockify source port mismatch; try to stop the recorded instance. - stop_ssh_tunnel($clean_up_parameters); - - return $ssh_tunnel_exists_info; - } - - if (not is_ssh_process($clean_up_parameters)) - { - # The recorded tunnel died. - return $ssh_tunnel_exists_info; - } - - # Passed all tests; tunnel considered exists. - $ssh_tunnel_exists_info->{exists_code} = 2; - } - - return $ssh_tunnel_exists_info; -} - -sub is_websockify_in_use_by_others -{ - my $parameters = shift; - my $ws_pid = $parameters->{ws_pid}; - - my $query = "SELECT COUNT(*) FROM public.vnc_pipes WHERE ws_pid = ".$anvil->Database->quote($ws_pid).";"; - - my $count = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ })->[0]->[0]; - - return $count > 1 ? 1 : 0; -} - -sub start_websockify -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_name = $parameters->{host_name}; my $host_uuid = $parameters->{host_uuid}; - my $target_port = $parameters->{target_port}; - my $source_port = $parameters->{source_port}; - my $ws_info; - - my $ws_exists_info = is_websockify_exists({ - server_uuid => $server_uuid, - host_uuid => $host_uuid, - server_vnc_port => $target_port - }); - - if ($ws_exists_info->{exists_code} == 2) - { - $ws_info = {}; - $ws_info->{pid} = $ws_exists_info->{ws_pid}; - $ws_info->{source_port} = $ws_exists_info->{ws_source_port}; - } - else - { - if (not defined $source_port) - { - if (defined $ws_exists_info->{ws_source_port}) - { - $source_port = $ws_exists_info->{ws_source_port}; - } - else - { - my $source_port_base = 10000; - - $source_port = $source_port_base + $target_port; - } - } - - my $shell_call = "websockify ".$source_port." :".$target_port." &>/dev/null & echo pid:\$!"; - - my ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call({ - target => $host_name, - remote_user => "admin", - shell_call => $shell_call, - 'close' => 1 - }); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - - if ($shell_return_code == 0) - { - my ($ws_pid) = $shell_output =~ /pid:(\d+)$/; - - $ws_info = {}; - $ws_info->{pid} = $ws_pid; - $ws_info->{source_port} = $source_port; - - if ($ws_exists_info->{exists_code} == 1) - { - $ws_info->{is_update} = 1; - } - else - { - $ws_info->{is_new} = 1; - } - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - ws_pid => $ws_pid, - ws_source_port => $source_port, - ws_is_update => $ws_info->{is_update}, - ws_is_new => $ws_info->{is_new} - } }); - } - } - - return $ws_info; -} -sub stop_websockify -{ - my $parameters = shift; - my $host_name = $parameters->{host_name}; - my $ws_pid = $parameters->{ws_pid}; - - if (is_websockify_process($parameters)) - { - my $shell_call = "kill ".$ws_pid; - my $remote_call_parameters = { - target => $host_name, - remote_user => "admin", - shell_call => $shell_call, - 'close' => 1 - }; - my $shell_output; - my $shell_error; - my $shell_return_code; - - ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call($remote_call_parameters); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - - sleep(2); - - if (is_websockify_process($parameters)) - { - $shell_call = $shell_call =~ s/kill/kill -9/; - $remote_call_parameters->{shell_call} = $shell_call; - - ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call($remote_call_parameters); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_return_code => $shell_return_code - } }); - } - } -} - -sub start_ssh_tunnel -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_uuid = $parameters->{host_uuid}; - my $ws_host_name = $parameters->{ws_host_name}; - my $ws_host_uuid = $parameters->{ws_host_uuid}; - my $ws_source_port = $parameters->{ws_source_port}; - my $ssh_tunnel_forward_port = $parameters->{ssh_tunnel_forward_port}; - my $ssh_tunnel_info; - - my $ssh_tunnel_exists_info = is_ssh_tunnel_exists({ - server_uuid => $server_uuid, - ssh_tunnel_host_uuid => $host_uuid, - ws_host_uuid => $ws_host_uuid, - ws_source_port => $ws_source_port - }); - - if ($ssh_tunnel_exists_info->{exists_code} == 2) - { - $ssh_tunnel_info = {}; - $ssh_tunnel_info->{pid} = $ssh_tunnel_exists_info->{ssh_tunnel_pid}; - $ssh_tunnel_info->{forward_port} = $ssh_tunnel_exists_info->{ssh_tunnel_forward_port}; - } - else - { - if (not defined $ssh_tunnel_forward_port) - { - if (defined $ssh_tunnel_exists_info->{ssh_tunnel_forward_port}) - { - $ssh_tunnel_forward_port = $ssh_tunnel_exists_info->{ssh_tunnel_forward_port}; - } - else - { - $ssh_tunnel_forward_port = $ws_source_port; - } - } - - my $shell_call = $anvil->data->{path}{exe}{'striker-open-ssh-tunnel'} - ." --remote-user admin --target ".$ws_host_name - ." --forward-local-port ".$ssh_tunnel_forward_port - ." --forward-remote-port ".$ws_source_port - ." &>/dev/null & echo pid:\$!"; - - my ($shell_output, $shell_return_code) = $anvil->System->call({ shell_call => $shell_call }); - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_return_code => $shell_return_code - } }); - - if ($shell_return_code == 0) - { - my ($ssh_tunnel_pid) = $shell_output =~ /pid:(\d+)$/; - - $ssh_tunnel_info = {}; - $ssh_tunnel_info->{pid} = $ssh_tunnel_pid; - $ssh_tunnel_info->{forward_port} = $ssh_tunnel_forward_port; - - if ($ssh_tunnel_exists_info->{exists_code} == 1) - { - $ssh_tunnel_info->{is_update} = 1; - } - else - { - $ssh_tunnel_info->{is_new} = 1; - } - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - ssh_tunnel_pid => $ssh_tunnel_pid, - ssh_tunnel_forward_port => $ssh_tunnel_forward_port, - ssh_tunnel_is_update => $ssh_tunnel_info->{is_update}, - ssh_tunnel_is_new => $ssh_tunnel_info->{is_new} - } }); - } - } - - return $ssh_tunnel_info; -} - -sub stop_ssh_tunnel -{ - my $parameters = shift; - my $host_name = $parameters->{host_name}; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - - if (is_ssh_process($parameters)) - { - my $shell_call = "kill ".$ssh_tunnel_pid; - my $is_remote_call = (defined $host_name) and ($host_name ne $anvil->Get->host_name()) ? 1 : 0; - my $remote_call_parameters = { - target => $host_name, - remote_user => "admin", - shell_call => $shell_call, - 'close' => 1 - }; - my $shell_output; - my $shell_error; - my $shell_return_code; - - if ($is_remote_call) - { - ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call($remote_call_parameters); - } - else - { - ($shell_output, $shell_return_code) = $anvil->System->call({ shell_call => $shell_call }); - } - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - - sleep(2); - - if (is_ssh_process($parameters)) - { - $shell_call = $shell_call =~ s/kill/kill -9/; - $remote_call_parameters->{shell_call} = $shell_call; - - if ($is_remote_call) - { - ($shell_output, $shell_error, $shell_return_code) = $anvil->Remote->call($remote_call_parameters); - } - else - { - ($shell_output, $shell_return_code) = $anvil->System->call({ shell_call => $shell_call }); - } - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - shell_call => $shell_call, - shell_output => $shell_output, - shell_error => $shell_error, - shell_return_code => $shell_return_code - } }); - } - } -} - -sub stop_related -{ - my $parameters = shift; - my $ws_pid = $parameters->{ws_pid}; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - my $select_pid_field; - my $condition_pid_field; - my $condition_pid_value; - my $stop_function; - - if (defined $ws_pid) - { - $select_pid_field = "ssh_tunnel_pid"; - $condition_pid_field = "ws_pid"; - $condition_pid_value = $ws_pid; - $stop_function = \&stop_ssh_tunnel - } - elsif (defined $ssh_tunnel_pid) - { - $select_pid_field = "ws_pid"; - $condition_pid_field = "ssh_tunnel_pid"; - $condition_pid_value = $ssh_tunnel_pid; - $stop_function = \&stop_websockify - } - - my $query = " -SELECT - hos.host_name, vnc.".$select_pid_field." -FROM - public.vnc_pipes AS vnc -JOIN - public.hosts AS hos -ON - vnc.ssh_tunnel_host_uuid = hos.host_uuid -WHERE - vnc.".$condition_pid_field." = ".$anvil->Database->quote($condition_pid_value)." -;"; - - my $results = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ }); - - foreach my $row (@{$results}) - { - $stop_function->({ host_name => $row->[0], ws_pid => $row->[1], ssh_tunnel_pid => $row->[1] }); - } -} - -sub create_vnc_pipes_table -{ - my $query = " -CREATE TABLE IF NOT EXISTS public.vnc_pipes ( - uuid uuid not null primary key, - server_uuid uuid not null, - server_vnc_port numeric not null, - ws_host_uuid uuid not null, - ws_pid numeric not null, - ws_source_port numeric not null, - ssh_tunnel_host_uuid uuid not null, - ssh_tunnel_pid numeric not null, - ssh_tunnel_forward_port numeric not null, - modified_date timestamp with time zone not null -);"; - - $anvil->Database->write({ query => $query, source => $THIS_FILE, line => __LINE__ }); -} - -sub drop_vnc_pipes_table -{ - my $query = "DROP TABLE IF EXISTS public.vnc_pipes;"; - - $anvil->Database->write({ query => $query, source => $THIS_FILE, line => __LINE__ }); -} - -sub insert_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $server_vnc_port = $parameters->{server_vnc_port}; - my $ws_host_uuid = $parameters->{ws_host_uuid}; - my $ws_pid = $parameters->{ws_pid}; - my $ws_source_port = $parameters->{ws_source_port}; - my $ssh_tunnel_host_uuid = $parameters->{ssh_tunnel_host_uuid}; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - my $ssh_tunnel_forward_port = $parameters->{ssh_tunnel_forward_port}; - - my $record_uuid = $anvil->Get->uuid(); - my $record_modified_date = $anvil->Database->refresh_timestamp(); - - my $query = " -INSERT INTO public.vnc_pipes ( - uuid, - server_uuid, - server_vnc_port, - ws_host_uuid, - ws_pid, - ws_source_port, - ssh_tunnel_host_uuid, - ssh_tunnel_pid, - ssh_tunnel_forward_port, - modified_date -) VALUES ( - ".$anvil->Database->quote($record_uuid).", - ".$anvil->Database->quote($server_uuid).", - ".$anvil->Database->quote($server_vnc_port).", - ".$anvil->Database->quote($ws_host_uuid).", - ".$anvil->Database->quote($ws_pid).", - ".$anvil->Database->quote($ws_source_port).", - ".$anvil->Database->quote($ssh_tunnel_host_uuid).", - ".$anvil->Database->quote($ssh_tunnel_pid).", - ".$anvil->Database->quote($ssh_tunnel_forward_port).", - ".$anvil->Database->quote($record_modified_date)." -);"; - - $anvil->Database->write({ query => $query, source => $THIS_FILE, line => __LINE__ }); -} - -sub update_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $server_vnc_port = $parameters->{server_vnc_port}; - my $ws_host_uuid = $parameters->{ws_host_uuid}; - my $ws_pid = $parameters->{ws_pid}; - my $ws_source_port = $parameters->{ws_source_port}; - my $ssh_tunnel_host_uuid = $parameters->{ssh_tunnel_host_uuid}; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - my $ssh_tunnel_forward_port = $parameters->{ssh_tunnel_forward_port}; - my $set_string; - my $condition_string = "server_uuid = ".$anvil->Database->quote($server_uuid); - - if ((defined $ws_host_uuid) and (defined $ws_pid) and (defined $ws_source_port)) - { - $set_string = " -server_vnc_port = ".$anvil->Database->quote($server_vnc_port).", -ws_host_uuid = ".$anvil->Database->quote($ws_host_uuid).", -ws_pid = ".$anvil->Database->quote($ws_pid).", -ws_source_port = ".$anvil->Database->quote($ws_source_port)." -"; - } - elsif ((defined $ssh_tunnel_host_uuid) and (defined $ssh_tunnel_pid) and (defined $ssh_tunnel_forward_port)) - { - $set_string = " -ssh_tunnel_host_uuid = ".$anvil->Database->quote($ssh_tunnel_host_uuid).", -ssh_tunnel_pid = ".$anvil->Database->quote($ssh_tunnel_pid).", -ssh_tunnel_forward_port = ".$anvil->Database->quote($ssh_tunnel_forward_port)." -"; - $condition_string = $condition_string." AND ssh_tunnel_host_uuid = ".$anvil->Database->quote($ssh_tunnel_host_uuid); - } - - my $query = " -UPDATE public.vnc_pipes -SET ".$set_string." -WHERE ".$condition_string." -;"; - - $anvil->Database->write({ query => $query, source => $THIS_FILE, line => __LINE__ }); -} - -sub get_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_uuid = $parameters->{host_uuid}; - my $vnc_pipe_info; + my $vnc_pipe_info = { protocol => "ws" }; my $query = " SELECT - hos.host_name, vnc.ws_pid, vnc.ssh_tunnel_pid + ssh_tunnel_forward_port FROM - public.vnc_pipes AS vnc -JOIN - public.hosts AS hos -ON - vnc.ws_host_uuid = hos.host_uuid -WHERE - server_uuid = ".$anvil->Database->quote($server_uuid)." -AND - ssh_tunnel_host_uuid = ".$anvil->Database->quote($host_uuid)." -;"; - - my $results = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ }); - my $count = @{$results}; - - if ($count == 1) - { - my $row = $results->[0]; - - $vnc_pipe_info = {}; - $vnc_pipe_info->{host_name} = $row->[0]; - $vnc_pipe_info->{ws_pid} = $row->[1]; - $vnc_pipe_info->{ssh_tunnel_pid} = $row->[2]; - - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - host_name => $vnc_pipe_info->{host_name}, - ws_pid => $vnc_pipe_info->{ws_pid}, - ssh_tunnel_pid => $vnc_pipe_info->{ssh_tunnel_pid} - } }); - } - - return $vnc_pipe_info; -} - -sub delete_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_uuid = $parameters->{host_uuid}; - my $ws_pid = $parameters->{ws_pid}; - my $ssh_tunnel_pid = $parameters->{ssh_tunnel_pid}; - - my $query = "DELETE FROM public.vnc_pipes "; - - if (defined $ws_pid) - { - $query = $query."WHERE ws_pid = ".$anvil->Database->quote($ws_pid).";"; - } - elsif (defined $ssh_tunnel_pid) - { - $query = $query."WHERE ssh_tunnel_pid = ".$anvil->Database->quote($ssh_tunnel_pid).";"; - } - else - { - $query = $query." + public.vnc_pipes WHERE server_uuid = ".$anvil->Database->quote($server_uuid)." AND ssh_tunnel_host_uuid = ".$anvil->Database->quote($host_uuid)." ;"; - } - $anvil->Database->write({ query => $query, source => $THIS_FILE, line => __LINE__ }); -} + my $forward_port = $anvil->Database->query({ query => $query, source => $THIS_FILE, line => __LINE__ })->[0]->[0]; -sub open_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $host_uuid = $anvil->Get->host_uuid(); - my $vnc_pipe_info; - - my $server_info = get_server_info({ server_uuid => $server_uuid }); - - if (not defined $server_info) - { - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - message => "Failed to get server VM information." - } }); - - return; - } - - my $vnc_info = get_vnc_info($server_info); - - if (not defined $vnc_info) - { - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - message => "Failed to get server VM VNC information." - } }); - - return; - } - - my $ws_info = start_websockify({ - server_uuid => $server_uuid, - host_name => $server_info->{host_name}, - host_uuid => $server_info->{host_uuid}, - target_port => $vnc_info->{port} - }); - - if (not defined $ws_info) - { - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - message => "Failed to get websockify instance information." - } }); - - return; - } - - my $ssh_tunnel_info = start_ssh_tunnel({ - server_uuid => $server_uuid, - host_uuid => $host_uuid, - ws_host_name => $server_info->{host_name}, - ws_host_uuid => $server_info->{host_uuid}, - ws_source_port => $ws_info->{source_port} - }); - - if (not defined $ssh_tunnel_info) - { - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - message => "Failed to get SSH tunnel instance information." - } }); - - return; - } - - if ($ws_info->{is_new} or $ssh_tunnel_info->{is_new}) - { - insert_vnc_pipe({ - server_uuid => $server_uuid, - server_vnc_port => $vnc_info->{port}, - ws_host_uuid => $server_info->{host_uuid}, - ws_pid => $ws_info->{pid}, - ws_source_port => $ws_info->{source_port}, - ssh_tunnel_host_uuid => $host_uuid, - ssh_tunnel_pid => $ssh_tunnel_info->{pid}, - ssh_tunnel_forward_port => $ssh_tunnel_info->{forward_port} - }); - } - else - { - if ($ws_info->{is_update}) - { - update_vnc_pipe({ - server_uuid => $server_uuid, - server_vnc_port => $vnc_info->{port}, - ws_host_uuid => $server_info->{host_uuid}, - ws_pid => $ws_info->{pid}, - ws_source_port => $ws_info->{source_port} - }); - } - - if ($ssh_tunnel_info->{is_update}) - { - update_vnc_pipe({ - server_uuid => $server_uuid, - ssh_tunnel_host_uuid => $host_uuid, - ssh_tunnel_pid => $ssh_tunnel_info->{pid}, - ssh_tunnel_forward_port => $ssh_tunnel_info->{forward_port} - }); - } - } - - $vnc_pipe_info = { forward_port => $ssh_tunnel_info->{forward_port} }; + $vnc_pipe_info->{forward_port} = $forward_port; return $vnc_pipe_info; } -sub close_vnc_pipe -{ - my $parameters = shift; - my $server_uuid = $parameters->{server_uuid}; - my $vnc_pipe_parameters = { server_uuid => $server_uuid, host_uuid => $anvil->Get->host_uuid() }; - my $vnc_pipe_info = get_vnc_pipe($vnc_pipe_parameters); - - if (not defined $vnc_pipe_info) - { - $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, list => { - message => "Failed to get VNC pipe information." - } }); - - return; - } - - if (not is_websockify_in_use_by_others({ ws_pid => $vnc_pipe_info->{ws_pid} })) - { - stop_websockify({ host_name => $vnc_pipe_info->{host_name}, ws_pid => $vnc_pipe_info->{ws_pid} }); - } - - stop_ssh_tunnel({ ssh_tunnel_pid => $vnc_pipe_info->{ssh_tunnel_pid} }); - - delete_vnc_pipe($vnc_pipe_parameters); -} - $anvil->Get->switches; $anvil->Database->connect; @@ -978,25 +100,28 @@ $anvil->Log->variables({ source => $THIS_FILE, line => __LINE__, level => 2, lis if ($server_uuid) { - create_vnc_pipes_table(); - - my $vnc_pipe_parameters = { server_uuid => $server_uuid }; + my $host_uuid = $anvil->Get->host_uuid(); + my $operation_string = $is_open ? "open" : "close"; + my $job_uuid = $anvil->Database->insert_or_update_jobs({ + job_command => $anvil->data->{path}{exe}{'striker-manage-vnc-pipes'}, + job_data => "server_uuid=".$server_uuid."\nopen=".$is_open, + job_host_uuid => $host_uuid, + job_description => "job_0351,!!operation!".$operation_string."!!,!!server_uuid!".$server_uuid."!!,!!host_uuid!".$host_uuid."!!", + job_name => "cgi-bin::manage_vnc_pipes::".$operation_string, + job_progress => 0, + job_title => "job_0350" + }); if ($is_open) { - my $vnc_pipe_info = open_vnc_pipe($vnc_pipe_parameters); + # Wait until the job is complete before fetching for the results. + while($anvil->Job->get_job_details({ job_uuid => $job_uuid })) + { + sleep(2); + } - $response_body->{protocol} = "ws"; - $response_body->{forward_port} = $vnc_pipe_info->{forward_port}; + $response_body = get_vnc_pipe_info({ server_uuid => $server_uuid, host_uuid => $host_uuid }); } - else - { - close_vnc_pipe($vnc_pipe_parameters); - } -} -elsif ($anvil->data->{switches}{'drop-table'}) -{ - drop_vnc_pipes_table(); } print JSON->new->utf8->encode($response_body)."\n"; diff --git a/share/words.xml b/share/words.xml index 554a2e9f..65a62e0a 100644 --- a/share/words.xml +++ b/share/words.xml @@ -1121,6 +1121,8 @@ It should be provisioned in the next minute or two. Both the BCN1 and SN1 links are working between the nodes. Checking corosync now... Synchronizing the new corosync config exited with return code: [#!variable!return_code!#] and output: [#!variable!output!#] Loading the new corosync config exited with return code: [#!variable!return_code!#] and output: [#!variable!output!#] + Manage VNC Pipes + Perform VNC pipe operation [#!variable!operation!#] for server UUID [#!variable!server_uuid!#] from host UUID [#!variable!host_uuid!#]. Manage a server menu: * Please enter the name of the server you want to manage