Added capability to deploy PostgreSQL servers on Amazon RDS. Fixes #7177

This commit is contained in:
Khushboo Vashi
2022-02-14 12:13:48 +05:30
committed by Akshay Joshi
parent b89e306df0
commit e61a1045f5
50 changed files with 3393 additions and 42 deletions

View File

@@ -14,7 +14,8 @@ the long running background-processes.
from flask import url_for
from flask_security import login_required
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_response, gone, success_return
from pgadmin.utils.ajax import make_response, gone, success_return,\
make_json_response
from .processes import BatchProcess
@@ -101,8 +102,26 @@ def acknowledge(pid):
Positive status
"""
try:
BatchProcess.acknowledge(pid)
return success_return()
process = BatchProcess(id=pid)
status, server = process.acknowledge(pid)
if status and len(server) > 0:
return make_json_response(
success=1,
data={'node': {
'sid': server['id'],
'gid': server['servergroup_id'],
'_type': 'server',
'icon': 'icon-server-not-connected',
'id': 'server_{}'.format(server['id']),
'label': server['name'],
'status': server['status'],
'cloud_status': server['cloud_status']
}}
)
elif status and len(server) == 0:
return success_return()
else:
return gone(errormsg=str(server))
except LookupError as lerr:
return gone(errormsg=str(lerr))

View File

@@ -20,6 +20,7 @@ from datetime import datetime
from pickle import dumps, loads
from subprocess import Popen, PIPE
import logging
import json
from pgadmin.utils import u_encode, file_quote, fs_encoding, \
get_complete_file_path, get_storage_directory, IS_WIN
@@ -487,6 +488,48 @@ class BatchProcess(object):
return pos, completed
def _get_cloud_instance_details(self, _process):
"""
Parse the output to get the cloud instance details
"""
ctime = get_current_time(format='%y%m%d%H%M%S%f')
stdout = []
stderr = []
out = 0
err = 0
cloud_server_id = 0
cloud_instance = ''
enc = sys.getdefaultencoding()
if enc == 'ascii':
enc = 'utf-8'
out, out_completed = self.read_log(
self.stdout, stdout, out, ctime, _process.exit_code, enc
)
err, err_completed = self.read_log(
self.stderr, stderr, err, ctime, _process.exit_code, enc
)
from pgadmin.misc.cloud import update_server
if out_completed and not _process.exit_code:
for value in stdout:
if 'instance' in value[1] and value[1] != '':
cloud_instance = json.loads(value[1])
cloud_server_id = _process.server_id
if type(cloud_instance) is dict and\
'instance' in cloud_instance:
cloud_instance['instance']['sid'] = cloud_server_id
cloud_instance['instance']['status'] = True
return update_server(cloud_instance)
elif err_completed and _process.exit_code > 0:
cloud_instance = {'instance': {}}
cloud_instance['instance']['sid'] = _process.server_id
cloud_instance['instance']['status'] = False
return update_server(cloud_instance)
return False, None
def status(self, out=0, err=0):
ctime = get_current_time(format='%y%m%d%H%M%S%f')
@@ -549,8 +592,7 @@ class BatchProcess(object):
},
'start_time': self.stime,
'exit_code': self.ecode,
'execution_time': execution_time,
'process_state': self.process_state
'execution_time': execution_time
}
@staticmethod
@@ -697,7 +739,8 @@ class BatchProcess(object):
"'{1}'").format(desc.sid, p.pid)
)
try:
BatchProcess.acknowledge(p.pid)
process = BatchProcess(id=p.pid)
process.acknowledge(p.pid)
except LookupError as lerr:
current_app.logger.warning(
_("Status for the background process '{0}' could "
@@ -712,8 +755,7 @@ class BatchProcess(object):
def total_seconds(dt):
return round(dt.total_seconds(), 2)
@staticmethod
def acknowledge(_pid):
def acknowledge(self, _pid):
"""
Acknowledge from the user, he/she has alredy watched the status.
@@ -721,6 +763,9 @@ class BatchProcess(object):
And, delete the process information from the configuration, and the log
files related to the process, if it has already been completed.
"""
status = True
_server = {}
p = Process.query.filter_by(
user_id=current_user.id, pid=_pid
).first()
@@ -729,15 +774,17 @@ class BatchProcess(object):
raise LookupError(PROCESS_NOT_FOUND)
if p.end_time is not None:
status, _server = self._get_cloud_instance_details(p)
logdir = p.logdir
db.session.delete(p)
import shutil
shutil.rmtree(logdir, True)
else:
p.acknowledge = get_current_time()
db.session.commit()
return status, _server
def set_env_variables(self, server, **kwargs):
"""Set environment variables"""
if server:
@@ -781,3 +828,16 @@ class BatchProcess(object):
p.utility_pid)
)
current_app.logger.exception(e)
@staticmethod
def update_server_id(_pid, _sid):
p = Process.query.filter_by(
user_id=current_user.id, pid=_pid
).first()
if p is None:
raise LookupError(PROCESS_NOT_FOUND)
# Update the cloud server id
p.server_id = _sid
db.session.commit()

View File

@@ -96,8 +96,10 @@ define('misc.bgprocess', [
pgBrowser.Events && pgBrowser.Events.on(
'pgadmin-bgprocess:finished:' + this.id,
function(process) {
if (!process.notifier)
if (!process.notifier) {
if (process.cloud_process == 1) process.update_cloud_server.apply(process);
process.show.apply(process);
}
}
);
}
@@ -175,6 +177,12 @@ define('misc.bgprocess', [
}
}
if ('cloud_process' in data && data.cloud_process == 1) {
self.cloud_process = data.cloud_process;
self.cloud_instance = data.cloud_instance;
self.cloud_server_id = data.cloud_server_id;
}
if ('err' in data) {
self.err = data.err && data.err.pos;
@@ -309,6 +317,46 @@ define('misc.bgprocess', [
});
},
update_cloud_server: function() {
var self = this,
_url = url_for('cloud.update_cloud_server'),
_data = {},
cloud_instance = self.cloud_instance;
if (cloud_instance != '') {
_data = JSON.parse(cloud_instance);
}
_data['instance']['sid'] = self.cloud_server_id;
$.ajax({
type: 'POST',
url: _url,
async: true,
data: JSON.stringify(_data),
contentType: 'application/json',
})
.done(function(res) {
setTimeout(function() {
let _server = res.data.node,
_server_path = '/browser/server_group_' + _server.gid + '/' + _server.id,
_tree = pgBrowser.tree,
_item = _tree.findNode(_server_path);
if (_item) {
_tree.addIcon(_item.domNode, {icon: _server.icon});
let d = _tree.itemData(_item);
d.cloud_status = 1;
_tree.update(_item, d);
}
}, 10);
})
.fail(function(res) {
// Try after some time only if job id present
if (res.status != 410)
console.warn('Failed Cloud Deployment.');
});
},
show: function() {
var self = this;
@@ -523,8 +571,30 @@ define('misc.bgprocess', [
async: true,
contentType: 'application/json',
})
.done(function() {
return;
.done(function(res) {
if (res.data && res.data.node) {
setTimeout(function() {
let _server = res.data.node,
_server_path = '/browser/server_group_' + _server.gid + '/' + _server.id,
_tree = pgBrowser.tree,
_item = _tree.findNode(_server_path);
if (_item) {
if(_server.status == true) {
let _dom = _item.domNode;
_tree.addIcon(_dom, {icon: _server.icon});
let d = _tree.itemData(_dom);
d.cloud_status = _server.cloud_status;
_tree.update(_dom, d);
}
else {
_tree.remove(_item.domNode);
_tree.refresh(_item.domNode.parent);
}
}
}, 10);
} else return;
})
.fail(function() {
console.warn(arguments);
@@ -595,7 +665,7 @@ define('misc.bgprocess', [
var observer = this;
$.ajax({
typs: 'GET',
type: 'GET',
timeout: 30000,
url: url_for('bgprocess.list'),
cache: false,