Docker: added pause/resume commands & container console window

This commit is contained in:
bergware
2018-05-01 09:37:31 +02:00
parent a199bed29c
commit a67787cade
9 changed files with 67 additions and 27 deletions

View File

@@ -33,6 +33,7 @@ img.stopped{opacity:0.3}
.iconstatus.stopped{font-size:1.2em}
.started{color:#009900}
.stopped{color:#EF3D47}
.paused{color:#F0DD33}
.switch-button-label.off{color:inherit}
th.five{width:5%}
th.eight{width:8%}

View File

@@ -260,6 +260,7 @@ class DockerTemplates {
$image = $ct['Image'];
$tmp = &$info[$name] ?? [];
$tmp['running'] = $ct['Running'];
$tmp['paused'] = $ct['Paused'];
$tmp['autostart'] = in_array($name, $autoStart);
if (!is_file($tmp['icon']) || $reload) $tmp['icon'] = $this->getIcon($image);
if ($ct['Running']) {
@@ -628,12 +629,24 @@ class DockerClient {
return $code;
}
public function pauseContainer($id) {
$this->getDockerJSON("/containers/$id/pause", 'POST', $code);
$this->flushCache($this::$containersCache);
return $code;
}
public function stopContainer($id) {
$this->getDockerJSON("/containers/$id/stop", 'POST', $code);
$this->flushCache($this::$containersCache);
return $code;
}
public function resumeContainer($id) {
$this->getDockerJSON("/containers/$id/unpause", 'POST', $code);
$this->flushCache($this::$containersCache);
return $code;
}
public function restartContainer($id) {
$this->getDockerJSON("/containers/$id/restart", 'POST', $code);
$this->flushCache($this::$containersCache);
@@ -696,6 +709,7 @@ class DockerClient {
$c['Name'] = substr($info['Name'], 1);
$c['Status'] = $ct['Status'] ?: 'None';
$c['Running'] = $info['State']['Running'];
$c['Paused'] = $info['State']['Paused'];
$c['Cmd'] = $ct['Command'];
$c['Id'] = $this->extractID($ct['Id']);
$c['Volumes'] = $info['HostConfig']['Binds'];

View File

@@ -43,18 +43,19 @@ $n = 0;
foreach ($containers as $ct) {
$name = $ct['Name'];
$id = $ct['Id'];
$running = $ct['Running'] ? 1 : 0;
$info = &$allInfo[$name];
$running = $info['running'] ? 1 : 0;
$paused = $info['paused'] ? 1 : 0;
$is_autostart = $info['autostart'] ? 'true':'false';
$updateStatus = $info['updated']=='true'||$info['updated']=='undef' ? 'true':'false';
$template = $info['template'];
$webGui = html_entity_decode($info['url']);
$support = html_entity_decode($info['Support']);
$project = html_entity_decode($info['Project']);
$menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,'%s','%s','%s','%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($template), $running, $updateStatus, $is_autostart, addslashes($webGui), $id, addslashes($support), addslashes($project));
$menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,%s,'%s','%s','%s','%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($template), $running, $paused, $updateStatus, $is_autostart, addslashes($webGui), $id, addslashes($support), addslashes($project));
$docker[] = "docker.push({name:'$name',id:'$id',state:$running,update:'$updateStatus'});";
$shape = $running ? 'play':'square';
$status = $running ? 'started':'stopped';
$shape = $running ? ($paused ? 'pause' : 'play') : 'square';
$status = $running ? ($paused ? 'paused' : 'started') : 'stopped';
$icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png';
$ports = [];
foreach ($ct['Ports'] as $port) {
@@ -69,15 +70,15 @@ foreach ($containers as $ct) {
}
echo "<tr><td style='width:48px;padding:4px'>";
echo "<div id='$id' style='display:block; cursor:pointer'><div style='position:relative;width:48px;height:48px;margin:0px auto'>";
echo "<img src='".htmlspecialchars($icon)."' class='".htmlspecialchars($status)."' style='position:absolute;top:0;bottom:0;left:0;right:0;width:48px;height:48px'>";
echo "<i class='fa iconstatus fa-$shape $status' title='".htmlspecialchars($status)."'></i></div></div>";
echo "<img src='".htmlspecialchars($icon)."' class='$status' style='position:absolute;top:0;bottom:0;left:0;right:0;width:48px;height:48px'>";
echo "<i class='fa iconstatus fa-$shape $status' title='$status'></i></div></div>";
echo "</td><td class='ct-name'>";
if ($template) {
echo "<a class='exec' onclick=\"editContainer('".addslashes(htmlspecialchars($name))."','".addslashes(htmlspecialchars($template))."')\">".htmlspecialchars($name)."</a>";
} else {
echo htmlspecialchars($name);
}
echo "<div class='advanced' style='width:160px'>Container ID: ".htmlspecialchars($id)."</div>";
echo "<div class='advanced' style='width:160px'>Container ID: $id</div>";
if ($ct['BaseImage']) echo "<div class='advanced' style='width:160px;'><i class='fa fa-cubes' style='margin-right:5px'></i>".htmlspecialchars(${ct['BaseImage']})."</div>";
echo "<div class='advanced' style='width:160px'>By:";
$registry = $info['registry'];

View File

@@ -27,9 +27,15 @@ switch ($action) {
case 'start':
if ($container) $arrResponse = ['success' => $DockerClient->startContainer($container)];
break;
case 'pause':
if ($container) $arrResponse = ['success' => $DockerClient->pauseContainer($container)];
break;
case 'stop':
if ($container) $arrResponse = ['success' => $DockerClient->stopContainer($container)];
break;
case 'resume':
if ($container) $arrResponse = ['success' => $DockerClient->resumeContainer($container)];
break;
case 'restart':
if ($container) $arrResponse = ['success' => $DockerClient->restartContainer($container)];
break;
@@ -85,8 +91,13 @@ switch ($action) {
exit;
}
break;
case 'terminal':
exec("kill \$(pgrep -a ttyd|awk '/\/$name\.sock/{print \$1}') 2>/dev/null");
@unlink("/var/tmp/$name.sock");
exec("exec ttyd -d 0 -i '/var/tmp/$name.sock' docker exec -it '$name' sh &>/dev/null &");
break;
default:
$arrResponse = ['error' => 'Unknown action \'' . $action . '\''];
$arrResponse = ['error' => "Unknown action '$action'"];
break;
}

View File

@@ -1,9 +1,10 @@
var eventURL = '/plugins/dynamix.docker.manager/include/Events.php';
function addDockerContainerContext(container, image, template, started, update, autostart, webui, id, Support, Project) {
function addDockerContainerContext(container, image, template, started, paused, update, autostart, webui, id, Support, Project) {
var opts = [{header:container, image:'/plugins/dynamix.docker.manager/images/dynamix.docker.manager.png'}];
if (started && (webui !== '' && webui != '#')) {
opts.push({text:'WebUI', icon:'fa-globe', href:webui, target:'_blank'});
if (started && !paused) {
if (webui !== '' && webui != '#') opts.push({text:'WebUI', icon:'fa-globe', href:webui, target:'_blank'});
opts.push({text:'Console', icon:'fa-terminal', action:function(e){e.preventDefault(); dockerTerminal(container);}});
opts.push({divider:true});
}
if (!update) {
@@ -11,7 +12,12 @@ function addDockerContainerContext(container, image, template, started, update,
opts.push({divider:true});
}
if (started) {
opts.push({text:'Stop', icon:'fa-stop', action:function(e){e.preventDefault(); eventControl({action:'stop', container:id}, 'loadlist');}});
if (paused) {
opts.push({text:'Resume', icon:'fa-play', action:function(e){e.preventDefault(); eventControl({action:'resume', container:id}, 'loadlist');}});
} else {
opts.push({text:'Pause', icon:'fa-pause', action:function(e){e.preventDefault(); eventControl({action:'pause', container:id}, 'loadlist');}});
opts.push({text:'Stop', icon:'fa-stop', action:function(e){e.preventDefault(); eventControl({action:'stop', container:id}, 'loadlist');}});
}
opts.push({text:'Restart', icon:'fa-refresh', action:function(e){e.preventDefault(); eventControl({action:'restart', container:id}, 'loadlist');}});
} else {
opts.push({text:'Start', icon:'fa-play', action:function(e){e.preventDefault(); eventControl({action:'start', container:id}, 'loadlist');}});
@@ -39,6 +45,14 @@ function addDockerImageContext(image, imageTag) {
opts.push({text:'Remove', icon:'fa-trash', action:function(e){e.preventDefault(); rmImage(image, imageTag);}});
context.attach('#'+image, opts);
}
function dockerTerminal(container) {
var height = 600;
var width = 900;
var top = (screen.height-height)/2;
var left = (screen.width-width)/2;
$.get(eventURL,{action:'terminal',name:container});
setTimeout(function(){window.open('/dockerterminal/'+container+'/', container, 'resizeable=yes,scrollbars=yes,height='+height+',width='+width+',top='+top+',left='+left).focus();},180);
}
function execUpContainer(container) {
var title = 'Updating the container: '+container;
var address = '/plugins/dynamix.docker.manager/include/CreateDocker.php?updateContainer=true&ct[]='+encodeURIComponent(container);
@@ -135,7 +149,7 @@ function rmImage(image, imageName) {
});
}
function eventControl(params, spin) {
if (spin) $('#'+params['container']).find('i').removeClass('fa-play fa-square').addClass('fa-refresh fa-spin');
if (spin) $('#'+params['container']).find('i').removeClass('fa-play fa-square fa-pause').addClass('fa-refresh fa-spin');
$.post(eventURL, params, function(data) {
if (data.success === true) {
if (spin) setTimeout(spin+'()',500); else location=window.location.href;
@@ -156,7 +170,7 @@ function startAll() {
}
function stopAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,ct; ct=docker[i]; i++) if (ct.state==1) $('#'+ct.id).find('i').removeClass('fa-play').addClass('fa-refresh fa-spin');
for (var i=0,ct; ct=docker[i]; i++) if (ct.state==1) $('#'+ct.id).find('i').removeClass('fa-play fa-pause').addClass('fa-refresh fa-spin');
$.post('/plugins/dynamix.docker.manager/include/ContainerManager.php',{action:'stop'},function(){loadlist();});
}
function checkAll() {

View File

@@ -38,7 +38,7 @@ div.Panel:hover{overflow:visible;z-index:10;background-color:unset}
</form>
<div id="dialog-confirm" style="display:none;" title="Dialog Title"></div>
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
<span class="status" style="margin-top:-44px; margin-right:<?= ($display['refresh']==0 || ($display['refresh']<0 && $var['mdResync']>0)) ? '60' : '0' ?>px"><input type="checkbox" class="appview"></span>
<span class="status" style="margin-top:-44px; margin-right:0"><input type="checkbox" class="appview"></span>
<div id="apps_icons" style="display:none"></div><div id="noapps">No apps available to show</div>
<script src="<?autov('/webGui/javascript/jquery.switchbutton.js')?>"></script>
@@ -51,8 +51,8 @@ function loadlist() {
$('#apps_icons').html(data[0]);
$('head').append('<script>'+data[1]+'<\/script>');
if ($.cookie('dashapps_view_mode')=='startedonly') {
$('.Panel').not('.started').hide();
if ($('.Panel.started').length===0) $('#noapps').show();
$('.Panel.stopped').hide();
if ($('.Panel.started').length===0 && $('.Panel.paused').length===0) $('#noapps').show();
}
if ($('.Panel').length===0) $('#noapps').show();
$('#apps_icons').slideDown('fast');
@@ -62,8 +62,8 @@ function loadlist() {
$(function() {
$('.appview').switchButton({labels_placement:"left", on_label:'Started Only', off_label:'All Apps', checked:$.cookie('dashapps_view_mode') == 'startedonly'});
$('.appview').change(function() {
$('.Panel').not('.started').finish().toggle('fast');
if ($('.Panel').length===0 || ($('.appview').is(':checked') && $('.Panel.started').length===0)) {
$('.Panel.stopped').finish().toggle('fast');
if ($('.Panel').length===0 || ($('.appview').is(':checked') && $('.Panel.started').length===0 && $('.Panel.paused').length===0)) {
$('#noapps').slideDown('fast');
} else {
$('#noapps').slideUp('fast');

View File

@@ -25,7 +25,7 @@ if (pgrep('dockerd')!==false && ($display=='icons' || $display=='docker')) {
$DockerClient = new DockerClient();
$DockerTemplates = new DockerTemplates();
$containers = $DockerClient->getDockerContainers();
$all_info = $DockerTemplates->getAllInfo();
$allInfo = $DockerTemplates->getAllInfo();
if (file_exists($user_prefs)) {
$prefs = parse_ini_file($user_prefs); $sort = [];
@@ -36,17 +36,18 @@ if (pgrep('dockerd')!==false && ($display=='icons' || $display=='docker')) {
foreach ($containers as $ct) {
$name = $ct['Name'];
$id = $ct['Id'];
$running = $ct['Running'] ? 1:0;
$info = &$all_info[$name];
$info = &$allInfo[$name];
$running = $info['running'] ? 1:0;
$paused = $info['paused'] ? 1:0;
$is_autostart = $info['autostart'] ? 'true':'false';
$updateStatus = $info['updated']=='true'||$info['updated']=='undef' ? 'true':'false';
$template = $info['template'];
$webGui = html_entity_decode($info['url']);
$support = html_entity_decode($info['Support']);
$project = html_entity_decode($info['Project']);
$menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,'%s','%s','%s','%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($template), $running, $updateStatus, $is_autostart, addslashes($webGui), $id, addslashes($support), addslashes($project));
$shape = $running ? 'play':'square';
$status = $running ? 'started':'stopped';
$menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,%s,'%s','%s','%s','%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($template), $running, $paused, $updateStatus, $is_autostart, addslashes($webGui), $id, addslashes($support), addslashes($project));
$shape = $running ? ($paused ? 'pause' : 'play') : 'square';
$status = $running ? ($paused ? 'paused' : 'started') : 'stopped';
$icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png';
echo "<div class='Panel $status'>";
echo "<div id='$id' style='display:block; cursor:pointer'>";

View File

@@ -77,7 +77,6 @@ span.tub span[id^='txt-tub']{margin-top:7px}
#title span.right{font-size:20px;padding-right:10px;float:right}
#title span img,#title p{display:none}
#title:first-child{margin-top:0}
#apps_icons{width:90%}
#clear{clear:both}
#footer{position:fixed;bottom:0;left:0;color:#808080;background:#121510;padding:5px 0;width:100%;height:16px;line-height:16px;text-align:center;z-index:100}
#statusraid{float:left;padding-left:10px}

View File

@@ -77,7 +77,6 @@ span.tub span[id^='txt-tub']{margin-top:7px}
#title span.right{font-size:20px;padding-right:10px;float:right}
#title span img,#title p{display:none}
#title:first-child{margin-top:0}
#apps_icons{width:90%}
#clear{clear:both}
#footer{position:fixed;bottom:0;left:0;color:#808080;background:#121510;padding:5px 0;width:100%;height:16px;line-height:16px;text-align:center;z-index:100}
#statusraid{float:left;padding-left:10px}