Skip to content

Commit

Permalink
storage: NFS clients
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Sep 22, 2017
1 parent d30e6de commit c020663
Show file tree
Hide file tree
Showing 10 changed files with 1,011 additions and 4 deletions.
86 changes: 86 additions & 0 deletions pkg/storaged/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@

var utils = require('./utils');

var nfs_mounts_py = require("raw!./nfs-mounts.py");
var pyinvoke = [ "sh", "-ec", "exec $(which python3 2>/dev/null || which python) $@", "--", "-" ];

/* STORAGED CLIENT
*/

Expand Down Expand Up @@ -404,6 +407,89 @@
return utils.compare_versions(this.manager.Version, version) < 0;
};

/* NFS mounts
*/

function nfs_mounts() {
var self = {
entries: [ ],

update_entry: update_entry,
add_entry: add_entry,
remove_entry: remove_entry,

entry_users: entry_users,

mount_entry: mount_entry,
unmount_entry: unmount_entry,
stop_and_unmount_entry: stop_and_unmount_entry,
stop_and_remove_entry: stop_and_remove_entry
};

function spawn_nfs_mounts(args) {
return cockpit.spawn(pyinvoke.concat(args),
{ superuser: "try", err: "message" })
.input(nfs_mounts_py);
}

var buf = "";
spawn_nfs_mounts([ "monitor" ])
.stream(function (output) {
var lines;

buf += output;
lines = buf.split("\n");
buf = lines[lines.length-1];
if (lines.length >= 2) {
self.entries = JSON.parse(lines[lines.length-2]);
$(self).triggerHandler('changed');
}
}).
fail(function (error) {
if (error != "closed") {
console.warn(error);
}
});

function update_entry(entry, new_fields) {
return spawn_nfs_mounts([ "update", JSON.stringify(entry), JSON.stringify(new_fields) ]);
}

function add_entry(fields) {
return spawn_nfs_mounts([ "add", JSON.stringify(fields) ]);
}

function remove_entry(entry) {
return spawn_nfs_mounts([ "remove", JSON.stringify(entry) ]);
}

function mount_entry(entry) {
return spawn_nfs_mounts([ "mount", JSON.stringify(entry) ]);
}

function unmount_entry(entry) {
return spawn_nfs_mounts([ "unmount", JSON.stringify(entry) ]);
}

function stop_and_unmount_entry(users, entry) {
var units = users.map(function (u) { return u.unit; });
return spawn_nfs_mounts([ "stop-and-unmount", JSON.stringify(units), JSON.stringify(entry) ]);
}

function stop_and_remove_entry(users, entry) {
var units = users.map(function (u) { return u.unit; });
return spawn_nfs_mounts([ "stop-and-remove", JSON.stringify(units), JSON.stringify(entry) ]);
}

function entry_users(entry) {
return spawn_nfs_mounts([ "users", JSON.stringify(entry) ]).then(JSON.parse);
}

return self;
}

client.nfs = nfs_mounts();

function init_manager() {
/* Storaged 2.6 and later uses the UDisks2 API names, but try the
* older storaged API first as a fallback.
Expand Down
2 changes: 2 additions & 0 deletions pkg/storaged/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
f.HasOptions = (f.Options.length > 0);
});

if (def.Action && def.Action.Danger)
def.Action.DangerButton = true;

function empty(obj) { return !obj || obj.length == 0; }

Expand Down
120 changes: 117 additions & 3 deletions pkg/storaged/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,109 @@ <h1 translatable="yes">The "storaged" API is not available on this system.</h1>
</div>
</script>

<script id="nfs-mounts-tmpl" type="x-template/mustache">
<div class="panel panel-default storage-mounts">
<div class="panel-heading">
<span class="pull-right">
{{#HasMounts}}
<button class="btn btn-default fa fa-check nfs-arm-button {{#armed}}active{{/armed}}"></button>
{{/HasMounts}}
<button class="btn btn-primary fa fa-plus" data-action="mount-add" ></button>
</span>
<span translatable="yes">NFS Mounts</span>
</div>
{{#HasMounts}}
<table class="table">
<thead>
<tr>
<th class="mount-name" translatable="yes">Server</th>
<th class="mount-point" translatable="yes">Mount Point</th>
{{#armed}}
<th class="mount-actions">&nbsp;</th>
{{/armed}}
{{^armed}}
<th class="mount-size-graph" translatable="yes">Size</th>
<th class="mount-size-number">&nbsp;</th>
{{/armed}}
</tr>
</thead>
<tbody>
{{#Mounts}}
<tr>
<td>
{{Server}} {{RemoteDir}}
</td>
<td>
{{MountPoint}}
</td>
{{#armed}}
<td class="text-right">
{{#IsMounted}}
<button translatable="yes" class="btn btn-default"
data-action="mount-unmount" data-arg="{{action_arg}}">Unmount</button>
{{/IsMounted}}
{{^IsMounted}}
<button translatable="yes" class="btn btn-default"
data-action="mount-mount" data-arg="{{action_arg}}">Mount</button>
{{/IsMounted}}
{{#CanEdit}}
<button class="btn btn-default pficon pficon-edit"
data-action="mount-edit" data-arg="{{action_arg}}"></button>
<button class="btn btn-danger pficon pficon-delete"
data-action="mount-remove" data-arg="{{action_arg}}"></button>
{{/CanEdit}}
</td>
{{/armed}}
{{^armed}}
{{#IsMounted}}
<td>
<div class="progress">
<div class="progress-bar {{#UsageCritical}}progress-bar-danger{{/UsageCritical}}"
data-width="{{UsagePercent}}%">
</div>
</div>
</td>
<td class="usage-text">
{{UsageText}}
</td>
{{/IsMounted}}
{{^IsMounted}}
<td>
Not mounted
</td>
<td>
</td>
{{/IsMounted}}
{{/armed}}
</tr>
{{/Mounts}}
</tbody>
</table>
{{/HasMounts}}
{{^HasMounts}}
<div translatable="yes" class="empty-panel-text">No NFS mounts set up</div>
{{/HasMounts}}
</div>
</script>

<script id="nfs-users-tmpl" type="x-template/mustache">
<div>
<p>{{Description}}</p>
<div class="nfs-users-table">
<table>
<tbody>
{{#Users}}
<tr>
<td>{{unit}}</td>
<td>{{desc}}</td>
</tr>
{{/Users}}
</tbody>
</table>
</div>
</div>
</script>

<script id="jobs-tmpl" type="x-template/mustache">
{{#HasJobs}}
<div class="panel panel-default">
Expand Down Expand Up @@ -335,6 +438,7 @@ <h1 translatable="yes">The "storaged" API is not available on this system.</h1>
</div>
<br/>
<div id="mounts"></div>
<div id="nfs-mounts"></div>
<div id="jobs"></div>
<div class="panel panel-default cockpit-log-panel">
<div class="panel-heading" translatable="yes">Storage Logs</div>
Expand Down Expand Up @@ -673,13 +777,14 @@ <h4 class="modal-title">{{Title}}</h4>
</table>
{{/HasMDRaidMembers}}
{{/Blocking}}
{{{Body}}}
<table class="form-table-ct">
{{#Fields}}
<tr>
{{#TextInput}}
<td class="top">{{Title}}</td>
<td>
<input class="form-control" type="text" {{#Value}}value="{{.}}"{{/Value}} data-field={{.}}>
<input class="form-control" {{#disabled}}disabled{{/disabled}} type="text" {{#Value}}value="{{.}}"{{/Value}} data-field={{.}}>
</td>
{{/TextInput}}
{{#PassInput}}
Expand Down Expand Up @@ -803,7 +908,7 @@ <h4 class="modal-title">{{Title}}</h4>
<td>
<div data-field={{.}} class="combobox-container">
<div class="input-group">
<input autocomplete="false" class="combobox form-control" type="text" value={{Value}} />
<input autocomplete="false" class="combobox form-control" type="text" {{#disabled}}disabled{{/disabled}} value={{Value}} />
<span class="form-control-feedback caret"></span>
<ul class="typeahead typeahead-long dropdown-menu">
</ul>
Expand Down Expand Up @@ -854,13 +959,22 @@ <h4 class="modal-title">{{Title}}</h4>
{{/MDRaidMembers}}
</table>
{{/HasMDRaidMembers}}
{{#HasUnits}}
<p translate>The filesystem is in use by system services or login sessions.<br>
Proceeding will stop these services and sessions.</p>
<table class="table table-bordered">
{{#Units}}
<tr><td><span class="pull-right">{{Name}}</span>{{Unit}}</td></tr>
{{/Units}}
</table>
{{/HasUnits}}
</div>
{{/Teardown}}
{{#Action}}
{{#Danger}}<div class="modal-footer-danger">{{.}}</div>{{/Danger}}
<div class="spinner spinner-sm pull-left" hidden></div>
<button class="btn btn-default" translatable="yes" data-action="cancel">Cancel</button>
<button class="btn {{#Danger}}btn-danger{{/Danger}}{{^Danger}}btn-primary{{/Danger}}"
<button class="btn {{#DangerButton}}btn-danger{{/DangerButton}}{{^DangerButton}}btn-primary{{/DangerButton}}"
data-action="apply">{{Title}}</button>
{{/Action}}
{{^Action}}
Expand Down

0 comments on commit c020663

Please sign in to comment.