Allow creation of named restore points.
parent
7513cebd8c
commit
23f0cf07ca
|
@ -70,6 +70,13 @@ class ServerModule(sg.ServerGroupPluginModule):
|
||||||
conn = manager.connection()
|
conn = manager.connection()
|
||||||
connected = conn.connected()
|
connected = conn.connected()
|
||||||
|
|
||||||
|
status, in_recovery = conn.execute_scalar("""
|
||||||
|
SELECT CASE WHEN usesuper
|
||||||
|
THEN pg_is_in_recovery()
|
||||||
|
ELSE FALSE
|
||||||
|
END as inrecovery
|
||||||
|
FROM pg_user WHERE usename=current_user""")
|
||||||
|
|
||||||
yield self.generate_browser_node(
|
yield self.generate_browser_node(
|
||||||
"%d" % (server.id),
|
"%d" % (server.id),
|
||||||
gid,
|
gid,
|
||||||
|
@ -82,7 +89,8 @@ class ServerModule(sg.ServerGroupPluginModule):
|
||||||
server_type=manager.server_type if connected else "pg",
|
server_type=manager.server_type if connected else "pg",
|
||||||
version=manager.version,
|
version=manager.version,
|
||||||
db=manager.db,
|
db=manager.db,
|
||||||
user=manager.user_info if connected else None
|
user=manager.user_info if connected else None,
|
||||||
|
in_recovery=in_recovery
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -181,6 +189,8 @@ class ServerNode(PGChildNodeView):
|
||||||
'module.js': [{}, {}, {'get': 'module_js'}],
|
'module.js': [{}, {}, {'get': 'module_js'}],
|
||||||
'reload':
|
'reload':
|
||||||
[{'get': 'reload_configuration'}],
|
[{'get': 'reload_configuration'}],
|
||||||
|
'restore_point':
|
||||||
|
[{'post': 'create_restore_point'}],
|
||||||
'connect': [{
|
'connect': [{
|
||||||
'get': 'connect_status', 'post': 'connect', 'delete': 'disconnect'
|
'get': 'connect_status', 'post': 'connect', 'delete': 'disconnect'
|
||||||
}]
|
}]
|
||||||
|
@ -781,5 +791,49 @@ class ServerNode(PGChildNodeView):
|
||||||
return make_json_response(data={'status': False,
|
return make_json_response(data={'status': False,
|
||||||
'result': gettext('Not connected to the server or the connection to the server has been closed.')})
|
'result': gettext('Not connected to the server or the connection to the server has been closed.')})
|
||||||
|
|
||||||
|
def create_restore_point(self, gid, sid):
|
||||||
|
"""
|
||||||
|
This method will creates named restore point
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gid: Server group ID
|
||||||
|
sid: Server ID
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
data = request.form
|
||||||
|
restore_point_name = data['value'] if data else None
|
||||||
|
from pgadmin.utils.driver import get_driver
|
||||||
|
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||||
|
conn = manager.connection()
|
||||||
|
|
||||||
|
# Execute SQL to create named restore point
|
||||||
|
if conn.connected():
|
||||||
|
if restore_point_name:
|
||||||
|
status, res = conn.execute_scalar(
|
||||||
|
"SELECT pg_create_restore_point('{0}');".format(
|
||||||
|
restore_point_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(
|
||||||
|
errormsg=str(res)
|
||||||
|
)
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
data={
|
||||||
|
'status': 1,
|
||||||
|
'result': gettext(
|
||||||
|
'Named restore point created: {0}'.format(
|
||||||
|
restore_point_name))
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error(
|
||||||
|
'Named restore point creation failed ({0})'.format(str(e))
|
||||||
|
)
|
||||||
|
return internal_server_error(errormsg=str(e))
|
||||||
|
|
||||||
ServerNode.register_node_view(blueprint)
|
ServerNode.register_node_view(blueprint)
|
||||||
|
|
|
@ -23,7 +23,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
category: 'create', priority: 1, label: '{{ _('Server...') }}',
|
category: 'create', priority: 1, label: '{{ _('Server...') }}',
|
||||||
data: {action: 'create'}, icon: 'wcTabIcon icon-server'
|
data: {action: 'create'}, icon: 'wcTabIcon icon-server'
|
||||||
}, {
|
},{
|
||||||
name: 'create_server', node: 'server', module: this,
|
name: 'create_server', node: 'server', module: this,
|
||||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||||
category: 'create', priority: 3, label: '{{ _('Server...') }}',
|
category: 'create', priority: 3, label: '{{ _('Server...') }}',
|
||||||
|
@ -33,18 +33,21 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||||
applies: ['object', 'context'], callback: 'connect_server',
|
applies: ['object', 'context'], callback: 'connect_server',
|
||||||
category: 'connect', priority: 4, label: '{{ _('Connect Server...') }}',
|
category: 'connect', priority: 4, label: '{{ _('Connect Server...') }}',
|
||||||
icon: 'fa fa-link', enable : 'is_not_connected'
|
icon: 'fa fa-link', enable : 'is_not_connected'
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
name: 'disconnect_server', node: 'server', module: this,
|
name: 'disconnect_server', node: 'server', module: this,
|
||||||
applies: ['object', 'context'], callback: 'disconnect_server',
|
applies: ['object', 'context'], callback: 'disconnect_server',
|
||||||
category: 'drop', priority: 5, label: '{{ _('Disconnect Server...') }}',
|
category: 'drop', priority: 5, label: '{{ _('Disconnect Server...') }}',
|
||||||
icon: 'fa fa-chain-broken', enable : 'is_connected'
|
icon: 'fa fa-chain-broken', enable : 'is_connected'
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
name: 'reload_configuration', node: 'server', module: this,
|
name: 'reload_configuration', node: 'server', module: this,
|
||||||
applies: ['tools', 'context'], callback: 'reload_configuration',
|
applies: ['tools', 'context'], callback: 'reload_configuration',
|
||||||
category: 'reload', priority: 6, label: '{{ _('Reload Configuration...') }}',
|
category: 'reload', priority: 6, label: '{{ _('Reload Configuration...') }}',
|
||||||
icon: 'fa fa-repeat', enable : 'enable_reload_config'
|
icon: 'fa fa-repeat', enable : 'enable_reload_config'
|
||||||
|
},{
|
||||||
|
name: 'restore_point', node: 'server', module: this,
|
||||||
|
applies: ['tools', 'context'], callback: 'restore_point',
|
||||||
|
category: 'restore', priority: 7, label: '{{ _('Add named restore point') }}',
|
||||||
|
icon: 'fa fa-anchor', enable : 'is_applicable'
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
pgBrowser.messages['PRIV_GRANTEE_NOT_SPECIFIED'] =
|
pgBrowser.messages['PRIV_GRANTEE_NOT_SPECIFIED'] =
|
||||||
|
@ -59,7 +62,18 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||||
return (node && node.connected == true);
|
return (node && node.connected == true);
|
||||||
},
|
},
|
||||||
enable_reload_config: function(node) {
|
enable_reload_config: function(node) {
|
||||||
if (node && node._type == "server" && node.connected == true) {
|
// Must be connected & is Super user
|
||||||
|
if (node && node._type == "server" &&
|
||||||
|
node.connected && node.user.is_superuser) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
is_applicable: function(node) {
|
||||||
|
// Must be connected & super user & not in recovery mode
|
||||||
|
if (node && node._type == "server" &&
|
||||||
|
node.connected && node.user.is_superuser
|
||||||
|
&& node.in_recovery == false) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -199,6 +213,46 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
},
|
||||||
|
/* Add restore point */
|
||||||
|
restore_point: function(args) {
|
||||||
|
var input = args || {};
|
||||||
|
obj = this,
|
||||||
|
t = pgBrowser.tree,
|
||||||
|
i = input.item || t.selected(),
|
||||||
|
d = i && i.length == 1 ? t.itemData(i) : undefined;
|
||||||
|
|
||||||
|
if (!d)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
alertify.prompt('{{ _('Enter the name of the restore point') }}', '',
|
||||||
|
// We will execute this function when user clicks on the OK button
|
||||||
|
function(evt, value) {
|
||||||
|
// If user has provided a value, send it to the server
|
||||||
|
if(!_.isUndefined(value) && !_.isNull(value) && value !== '') {
|
||||||
|
$.ajax({
|
||||||
|
url: obj.generate_url(i, 'restore_point', d, true),
|
||||||
|
method:'POST',
|
||||||
|
data:{ 'value': JSON.stringify(value) },
|
||||||
|
success: function(res) {
|
||||||
|
alertify.success(res.data.result, 10);
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
try {
|
||||||
|
var err = $.parseJSON(xhr.responseText);
|
||||||
|
if (err.success == 0) {
|
||||||
|
alertify.error(err.errormsg, 10);
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
t.unload(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alertify.error('{{ _('Please enter a valid name.') }}', 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
model: pgAdmin.Browser.Node.Model.extend({
|
model: pgAdmin.Browser.Node.Model.extend({
|
||||||
|
|
Loading…
Reference in New Issue