From 9f8aea610c62814149ad9408ba86337603f54df9 Mon Sep 17 00:00:00 2001
From: Pavel Loginov
Date: Sun, 22 Sep 2019 18:46:26 +0300
Subject: [PATCH] v3.4.9
New the overview HAProxy-WI page
New the overview HAProxy page
---
app/create_db.py | 2 +-
app/hapservers.py | 57 ++++++
app/overview.py | 3 +
app/ovw.py | 34 ++--
app/templates/ajax/config_show.html | 1 +
app/templates/ajax/overivewWaf.html | 11 +-
app/templates/ajax/overview.html | 19 +-
app/templates/ajax/overviewServers.html | 62 +++---
app/templates/base.html | 2 +-
app/templates/configver.html | 5 +-
app/templates/delver.html | 9 +-
app/templates/hapservers.html | 49 +++++
app/templates/ovw.html | 67 +++---
app/templates/waf.html | 4 +-
inc/awesome.css | 1 +
inc/overview.js | 6 +-
inc/script.js | 34 +++-
inc/style.css | 257 +++++++++++++++---------
18 files changed, 429 insertions(+), 194 deletions(-)
create mode 100644 app/hapservers.py
create mode 100644 app/templates/hapservers.html
diff --git a/app/create_db.py b/app/create_db.py
index 354f0c95..6c39b50e 100644
--- a/app/create_db.py
+++ b/app/create_db.py
@@ -401,7 +401,7 @@ def update_db_v_3_4_7(**kwargs):
def update_ver(**kwargs):
con, cur = get_cur()
- sql = """update version set version = '3.4.8.1'; """
+ sql = """update version set version = '3.4.9'; """
try:
cur.execute(sql)
con.commit()
diff --git a/app/hapservers.py b/app/hapservers.py
new file mode 100644
index 00000000..7d522b12
--- /dev/null
+++ b/app/hapservers.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+import funct, sql
+import create_db
+import os, http.cookies
+from jinja2 import Environment, FileSystemLoader
+env = Environment(loader=FileSystemLoader('templates/'))
+template = env.get_template('hapservers.html')
+
+print('Content-type: text/html\n')
+
+
+try:
+ cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
+ user_id = cookie.get('uuid')
+ user = sql.get_user_name_by_uuid(user_id.value)
+ users = sql.select_users()
+ groups = sql.select_groups()
+ token = sql.get_token(user_id.value)
+ servers = sql.get_dick_permit()
+except:
+ pass
+
+haproxy_sock_port = sql.get_setting('haproxy_sock_port')
+
+servers_with_status1 = []
+out1 = ""
+for s in servers:
+ # print(s[2])
+ servers_with_status = list()
+ cmd = 'echo "show info" |nc %s %s -w 1 |grep -e "Ver\|Uptime:"' % (s[2], haproxy_sock_port)
+ # print(cmd )
+ out = funct.subprocess_execute(cmd)
+ servers_with_status.append(s[0])
+ servers_with_status.append(s[1])
+ servers_with_status.append(s[2])
+ servers_with_status.append(s[11])
+ for k in out:
+ if "Ncat: Connection refused." not in k and "Ncat: Connection timed out." not in k:
+ out1 = out
+ else:
+ out1 = False
+ servers_with_status.append(out1)
+
+ servers_with_status1.append(servers_with_status)
+# print(servers_with_status1)
+
+template = template.render(h2 = 1,
+ autorefresh = 1,
+ title = "HAProxy servers overview",
+ role = sql.get_user_role_by_uuid(user_id.value),
+ user = user,
+ users = users,
+ groups = groups,
+ servers = servers_with_status1,
+ versions = funct.versions(),
+ token = token)
+print(template)
diff --git a/app/overview.py b/app/overview.py
index 5737a62a..dc91e6d2 100644
--- a/app/overview.py
+++ b/app/overview.py
@@ -28,6 +28,8 @@ try:
metrics_master, stderr = funct.subprocess_execute(cmd)
cmd = "ps ax |grep -e 'metrics_worker\|metrics_waf_worker.py' |grep -v grep |wc -l"
metrics_worker, stderr = funct.subprocess_execute(cmd)
+ cmd = "ps ax |grep -e 'keep_alive.py' |grep -v grep |wc -l"
+ keep_alive, stderr = funct.subprocess_execute(cmd)
except:
pass
@@ -43,6 +45,7 @@ template = template.render(h2 = 1,
metrics_worker = ''.join(metrics_worker),
checker_master = ''.join(checker_master),
checker_worker = ''.join(checker_worker),
+ keep_alive = ''.join(keep_alive),
error = stderr,
versions = funct.versions(),
token = token)
diff --git a/app/ovw.py b/app/ovw.py
index fb41d843..df9eafd2 100644
--- a/app/ovw.py
+++ b/app/ovw.py
@@ -15,15 +15,14 @@ server_status = ()
async def async_get_overview(serv1, serv2):
haproxy_config_path = sql.get_setting('haproxy_config_path')
commands = [ "ls -l %s |awk '{ print $6\" \"$7\" \"$8}'" % haproxy_config_path ]
- commands1 = [ "ps ax |grep waf/bin/modsecurity |grep -v grep |wc -l" ]
+ # commands1 = [ "ps ax |grep waf/bin/modsecurity |grep -v grep |wc -l" ]
commands2 = "ps ax |grep keep_alive.py |grep -v grep |wc -l"
- cmd = 'echo "show info" |nc %s %s |grep -e "Process_num"' % (serv2, haproxy_sock_port)
+ cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Process_num"' % (serv2, haproxy_sock_port)
server_status = (serv1,
serv2,
funct.server_status(funct.subprocess_execute(cmd)),
- funct.ssh_command(serv2, commands),
- funct.ssh_command(serv2, commands1),
+ funct.ssh_command(serv2, commands),
sql.select_servers(server=serv2, keep_alive=1),
funct.subprocess_execute(commands2))
return server_status
@@ -68,8 +67,13 @@ def get_overviewWaf(url):
ioloop.close()
async def async_get_overviewServers(serv1, serv2, desc):
- commands = [ "top -u haproxy -b -n 1" ]
- cmd = 'echo "show info" |nc %s %s |grep -e "Ver\|CurrConns\|SessRate\|Maxco\|MB\|Uptime:"' % (serv2, haproxy_sock_port)
+ # commands = [ "top -u haproxy -b -n 1" ]
+ # commands = [ "top -u haproxy -b -n 1 -o %MEM |grep -e 'haproxy\|PID' |awk '{print $1\"\t\"$5\"\t\"$9\"\t\"$10\"\t\"$11}'" ]
+ commands = [ "top -u haproxy -b -n 1 -w 67 |grep -e 'haproxy\|PID\|Cpu\|KiB' |grep -v Swap" ]
+ if desc == "hapservers.py":
+ cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|Maxco\|MB\|Uptime:"' % (serv2, haproxy_sock_port)
+ else:
+ cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|SessRate\|Maxco\|MB\|Uptime:"' % (serv2, haproxy_sock_port)
out = funct.subprocess_execute(cmd)
out1 = ""
user_id = cookie.get('uuid')
@@ -81,7 +85,7 @@ async def async_get_overviewServers(serv1, serv2, desc):
os.system("/bin/rm -f " + cfg)
for k in out:
- if "Ncat: Connection refused." not in k:
+ if "Ncat: Connection refused." not in k and "Ncat: Connection timed out." not in k:
for r in k:
out1 += r
out1 += " "
@@ -95,21 +99,27 @@ async def async_get_overviewServers(serv1, serv2, desc):
return server_status
-async def get_runner_overviewServers():
+async def get_runner_overviewServers(**kwargs):
template = env.get_template('overviewServers.html')
user_id = cookie.get('uuid')
role = sql.get_user_role_by_uuid(user_id.value)
- futures = [async_get_overviewServers(server[1], server[2], server[11]) for server in listhap]
+ if kwargs.get('server1'):
+ futures = [async_get_overviewServers(kwargs.get('server1'), kwargs.get('server2'), 'hapservers.py')]
+ else:
+ futures = [async_get_overviewServers(server[1], server[2], server[11]) for server in listhap]
for i, future in enumerate(asyncio.as_completed(futures)):
result = await future
servers.append(result)
servers_sorted = sorted(servers, key=funct.get_key)
- template = template.render(service_status=servers_sorted, role=role)
+ template = template.render(service_status=servers_sorted, role=role,page=kwargs.get('page'))
print(template)
-def get_overviewServers():
+def get_overviewServers(**kwargs):
+ server1 = kwargs.get('name')
+ server2 = kwargs.get('ip')
+ page = kwargs.get('page')
ioloop = asyncio.get_event_loop()
- ioloop.run_until_complete(get_runner_overviewServers())
+ ioloop.run_until_complete(get_runner_overviewServers(server1=server1, server2=server2,page=page))
ioloop.close()
def get_map(serv):
diff --git a/app/templates/ajax/config_show.html b/app/templates/ajax/config_show.html
index 9099e872..a74d9769 100644
--- a/app/templates/ajax/config_show.html
+++ b/app/templates/ajax/config_show.html
@@ -117,5 +117,6 @@
Just save
Upload and restart
+ Note: If you reconfigure Master server, Slave will reconfigured automatically
{% endif %}
diff --git a/app/templates/ajax/overivewWaf.html b/app/templates/ajax/overivewWaf.html
index d00c25f2..c6b21ca6 100644
--- a/app/templates/ajax/overivewWaf.html
+++ b/app/templates/ajax/overivewWaf.html
@@ -4,14 +4,15 @@
{% do waf_servers.append(1) %}
+ {% if service.2|int() >= 1 %}
+ UP
+ {% else %}
+ DOWN
+ {% endif %}
{{ service.0 }}
- {% if service.2|int() >= 1 %}
- UP running {{service.2 }} processes
- {% else %}
- DOWN running {{service.2 }} processes
- {% endif %}
+
{% if role <= 1 %}
diff --git a/app/templates/ajax/overview.html b/app/templates/ajax/overview.html
index a70caf82..43387a57 100644
--- a/app/templates/ajax/overview.html
+++ b/app/templates/ajax/overview.html
@@ -1,12 +1,17 @@
{% for service in service_status %}
-
-
+
+ {% if service.2|int() >= 1 %}
+ UP
+ {% else %}
+ DOWN
+ {% endif %}
+
{{ service.0 }}
- {% if service.5.0.0|int() >= 1 %}
+ {% if service.4.0.0|int() >= 1 %}
= 1 %}
+ {% if service.5.0.0|int() >= 1 %}
src="/inc/images/shield.png" title="Auto start enabled"
{% else %}
src="/inc/images/shield-red.png" title="Auto start enabled, but keep alive service does not work"
@@ -17,11 +22,7 @@
- {% if service.2|int() >= 1 %}
- UP running {{service.2 }} processes
- {% else %}
- DOWN running {{service.2 }} processes
- {% endif %}
+
{% if role <= 1 %}
diff --git a/app/templates/ajax/overviewServers.html b/app/templates/ajax/overviewServers.html
index cdb350a9..14ad90ff 100644
--- a/app/templates/ajax/overviewServers.html
+++ b/app/templates/ajax/overviewServers.html
@@ -1,36 +1,46 @@
{% for service in service_status %}
-
-
+
+
+ {% if page != 'hapservers.py' %}
+
{% if service.5 != "None" %}
{{ service.0 }} :
{% else %}
{{ service.0 }} :
{% endif %}
-
-
-
-{{ service.2 }}
-
-
-
-
-{{ service.3 }}
-
-
-
-
- {% if 'Unknown command' in service.4 %}
-Too old version HAProxy
- {% else %}
- {% for s in service.4 %}
-
-{{s}}
-
- {% endfor %}
+
{% endif %}
+
+
+{{ service.2 }}
+
+
+
+ {% if page != 'hapservers.py' %}
+
+
+ {% if 'Unknown command' in service.4 %}
+ Too old version HAProxy
+ {% else %}
+ {% for s in service.4 %}
+ {% if role <= 2 %}
+
+ {{s}}
+
+ {% else %}
+ {{ s }}
+ {% endif %}
+
+ {% endfor %}
+ {% endif %}
-
-
-
+
+ {% endif %}
+
+
{% endfor %}
\ No newline at end of file
diff --git a/app/templates/base.html b/app/templates/base.html
index a839e992..00347286 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -42,7 +42,7 @@
+
{% endif %}
{% if aftersave %}
diff --git a/app/templates/delver.html b/app/templates/delver.html
index 837200b0..05527c35 100644
--- a/app/templates/delver.html
+++ b/app/templates/delver.html
@@ -16,10 +16,12 @@
Open
+ {% if not aftersave and not open %}
+
+ Here you can work with previous versions of HAProxy configs. Roll back to them, view or delete
+
+ {% endif %}
- {% if note %}
- Note: If you reconfigure Master server, Slave will reconfigured automatically
- {% endif %}
{% if open %}
Choose old version
@@ -40,6 +42,7 @@
+ Note: If you reconfigure Master server, Slave will reconfigured automatically
{% endif %}
{% if aftersave %}
The following files were deleted:
diff --git a/app/templates/hapservers.html b/app/templates/hapservers.html
new file mode 100644
index 00000000..851271b5
--- /dev/null
+++ b/app/templates/hapservers.html
@@ -0,0 +1,49 @@
+{% extends "base.html" %}
+{% block content %}
+{% for s in servers %}
+
+
+
+
+ {% if s.5 != False %}
+
+ {% else %}
+
+ {% endif %}
+
{{s.1}}
+ {% if role <= 1 %}
+
+
+
+
+
+
+
+
+
+
+
+ {% endif %}
+
+
+ {{s.3}}
+
+
+
+
+
+{% endfor %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/app/templates/ovw.html b/app/templates/ovw.html
index 12db6fac..27a7342d 100644
--- a/app/templates/ovw.html
+++ b/app/templates/ovw.html
@@ -7,7 +7,7 @@
Login
- Email
+
Group
Role
@@ -29,7 +29,7 @@
- {{ USER.2 }}
+
{% for group in groups %}
{% if USER.5 == group.0|string() %}
{{ group.1 }}
@@ -73,8 +73,8 @@
DOWN
{% endif %}
Metrics master
-
-
+
+
{% if metrics_worker|int() >= 1 %}
UP
{% else %}
@@ -82,6 +82,7 @@
{% endif %}
Metrics workers
+
{% if checker_master|int() >= 1 %}
UP
@@ -89,8 +90,8 @@
DOWN
{% endif %}
Checker master
-
-
+
+
{% if checker_worker|int() >= 1 %}
UP
{% else %}
@@ -98,6 +99,14 @@
{% endif %}
Checker workers
+
+ {% if keep_alive|int() >= 1 %}
+ UP
+ {% else %}
+ DOWN
+ {% endif %}
+ Keep alive
+
{% endif %}
@@ -107,7 +116,7 @@
Server
- HAproxy status
+
Action
@@ -124,10 +133,10 @@
- Server
+ WAF
- WAF status
+
Action
@@ -141,26 +150,26 @@
-
-
-
- Server
-
-
- HAproxy info
-
-
- Server status
-
-
- Front/Back-ends
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/templates/waf.html b/app/templates/waf.html
index d1d1f86c..8faa6255 100644
--- a/app/templates/waf.html
+++ b/app/templates/waf.html
@@ -4,9 +4,9 @@
Server
-
+
- WAF status
+
Action
diff --git a/inc/awesome.css b/inc/awesome.css
index 5cd1985a..39dce231 100644
--- a/inc/awesome.css
+++ b/inc/awesome.css
@@ -1,5 +1,6 @@
.menu .svg-inline--fa {
margin-right: 0.5em;
+ width: 1.5em;
}
.auto-refresh-pause::before {
display: none;
diff --git a/inc/overview.js b/inc/overview.js
index 52e13396..69dfafa6 100644
--- a/inc/overview.js
+++ b/inc/overview.js
@@ -14,7 +14,11 @@ function ajaxActionServers(action, id) {
if( data == 'Bad config, check please ' ) {
alert(data);
} else {
- setTimeout(showOverview, 2000)
+ if (cur_url[0] == "hapservers.py") {
+ location.reload()
+ } else {
+ setTimeout(showOverview, 2000)
+ }
}
},
error: function(){
diff --git a/inc/script.js b/inc/script.js
index a0369f28..c59f6975 100644
--- a/inc/script.js
+++ b/inc/script.js
@@ -146,8 +146,7 @@ function startSetInterval(interval) {
}
intervalId = setInterval('loadMetrics()', interval);
loadMetrics();
- }
- else if (cur_url[0] == "waf.py") {
+ } else if (cur_url[0] == "waf.py") {
if(interval < 60000) {
interval = 60000;
}
@@ -190,7 +189,7 @@ $( document ).ajaxComplete(function( event, request, settings ) {
});
function showOverview() {
- showOverviewServers();
+ // showOverviewServers();
showOverviewWaf()
$.ajax( {
url: "options.py",
@@ -206,6 +205,35 @@ function showOverview() {
}
} );
}
+function showOverviewServer(name,ip,id) {
+ showOverviewServers();
+ showOverviewWaf()
+ $.ajax( {
+ url: "options.py",
+ data: {
+ act: "overviewServers",
+ name: name,
+ serv: ip,
+ page: 'hapservers.py',
+ token: $('#token').val()
+ },
+ type: "GET",
+ success: function( data ) {
+ $("#ajax-server-"+id).empty();
+ $("#ajax-server-"+id).css('display', 'block');
+ $("#ajax-server-"+id).css('background-color', '#f9fff8');
+ $("#ajax-server-"+id).css('border', '1px solid #ddd');
+ $(".ajax-server").css('display', 'block');
+ $(".div-server").css('clear', 'both');
+ $(".div-pannel").css('clear', 'both');
+ $(".div-pannel").css('display', 'block');
+ $(".div-pannel").css('padding-top', '10px');
+ $(".div-pannel").css('height', '70px');
+ $("#ajax-server-"+id).html(data);
+ // $.getScript('/inc/overview.js');
+ }
+ } );
+}
function showOverviewWaf() {
$.ajax( {
url: "options.py",
diff --git a/inc/style.css b/inc/style.css
index 3b238251..d7089775 100644
--- a/inc/style.css
+++ b/inc/style.css
@@ -31,12 +31,11 @@ h3 {
form {
margin: 0;
}
-iframe {
- width: 33%;
-}
+/* iframe { */
+ /* width: 33%; */
+/* } */
pre {
padding-left: 15px;
- //padding-top: 20px;
}
.icon {
@@ -55,8 +54,6 @@ pre {
left: 0;
z-index: 1000;
display: block;
-}
-.top-menu {
background-color: #292e34;
}
.logoText {
@@ -70,8 +67,8 @@ pre {
padding-top: 2px;
}
#logo_text {
-display: block;
-margin-top: -4px;
+ display: block;
+ margin-top: -4px;
}
.top-menu img {
max-width: 125px;
@@ -235,20 +232,20 @@ margin-top: -4px;
.paramInSec {
font-weight: bold;
}
-.conteinerIndex {
- width: 20%;
- background-color: #fff;
- padding: 20px;
- border-radius: 10px;
- margin-top: 2%;
-}
-.conteinerIndex img {
- max-width: 250px;
-}
-.copyright {
- color: #23527c;
- margin-left: 15px;
-}
+/* .conteinerIndex { */
+ /* width: 20%; */
+ /* background-color: #fff; */
+ /* padding: 20px; */
+ /* border-radius: 10px; */
+ /* margin-top: 2%; */
+/* } */
+/* .conteinerIndex img { */
+ /* max-width: 250px; */
+/* } */
+/* .copyright { */
+ /* color: #23527c; */
+ /* margin-left: 15px; */
+/* } */
.copyright-menu {
font-weight: bold;
font-style: italic;
@@ -280,9 +277,6 @@ margin-top: -4px;
padding-left: 0;
padding-right: 0;
}
-.overviewHead:hover {
- background-color: #f4f9f3e6;
-}
.comment {
color: #aaa;
}
@@ -334,12 +328,16 @@ margin-top: -4px;
}
.overview {
width: 100%;
+ /* margin-top: 1.5em; */
}
.overviewHead {
border-radius: 5px;
- background-color: #f4f9f3e6;
+ background-color: #F9FFF8;
font-weight: bold;
}
+/* .overviewHead:hover { */
+ /* background-color: #f4f9f3e6; */
+/* } */
.overview tr{
border-bottom: 1px solid #ddd;
border-radius: 5px;
@@ -407,10 +405,10 @@ margin-top: -4px;
width: 15%;
}
.second-collumn {
- width: 25%;
+ width: 20%;
}
.third-collumn {
- width: 35%;
+ width: 45%;
}
.ro {
border: none;
@@ -425,7 +423,6 @@ margin-top: -4px;
padding: 5px;
border-radius: 3px;
}
-
ul{
margin: 0;
padding: 0;
@@ -581,75 +578,6 @@ a {
a:active, a:hover {
outline: 0;
}
-abbr[title] {
- border-bottom: 1px dotted;
-}
-b,
-strong {
- font-weight: bold;
-}
-//button,
-input,
-optgroup,
-select,
-textarea {
- margin: 0;
- font: inherit;
- color: inherit;
- border-radius: 7px;
- padding: 3px;
-}
-button {
- overflow: visible;
-}
-button,
-select {
- text-transform: none;
-}
-select {
- color: #000;
-}
-button {
- background-color: #337ab7;
- border-color: #2e6da4;
- color: #fff;
-}
-button,
-html input[type="button"],
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button;
- cursor: pointer;
-}
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- padding: 0;
- border: 0;
-}
-input {
- line-height: normal;
- border-radius: 4px;
-}
-
-table {
- border-spacing: 0;
- border-collapse: collapse;
- background-color: transparent;
- width: 100%;
-}
-caption {
- color: #777;
- text-align: left;
-}
-td,th {
- padding: 0;
- text-align: left;
- min-width: 30px;
-}
a,
a:visited {
text-decoration: underline;
@@ -667,6 +595,76 @@ a:focus {
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
+/* abbr[title] { */
+ /* border-bottom: 1px dotted; */
+/* } */
+/* b, */
+/* strong { */
+ /* font-weight: bold; */
+/* } */
+/* //button, */
+/* input, */
+/* optgroup, */
+/* select, */
+/* textarea { */
+ /* margin: 0; */
+ /* font: inherit; */
+ /* color: inherit; */
+ /* border-radius: 7px; */
+ /* padding: 3px; */
+/* } */
+/* button { */
+ /* overflow: visible; */
+/* } */
+/* button, */
+/* select { */
+ /* text-transform: none; */
+/* } */
+/* select { */
+ /* color: #000; */
+/* } */
+/* button { */
+ /* background-color: #337ab7; */
+ /* border-color: #2e6da4; */
+ /* color: #fff; */
+/* } */
+/* button, */
+/* html input[type="button"], */
+/* input[type="reset"], */
+/* input[type="submit"] { */
+ /* -webkit-appearance: button; */
+ /* cursor: pointer; */
+/* } */
+/* button[disabled], */
+/* html input[disabled] { */
+ /* cursor: default; */
+/* } */
+/* button::-moz-focus-inner, */
+/* input::-moz-focus-inner { */
+ /* padding: 0; */
+ /* border: 0; */
+/* } */
+/* input { */
+ /* line-height: normal; */
+ /* border-radius: 4px; */
+/* } */
+
+table {
+ border-spacing: 0;
+ border-collapse: collapse;
+ background-color: transparent;
+ width: 100%;
+}
+caption {
+ color: #777;
+ text-align: left;
+}
+td,th {
+ padding: 0;
+ text-align: left;
+ min-width: 30px;
+}
+
.row {
margin-right: -15px;
margin-left: -15px;
@@ -742,4 +740,65 @@ label {
/* .mCSB_container { */
/* overflow-y: hidden !important; */
/* overflow-x: auto !important; */
-/* } */
\ No newline at end of file
+/* } */
+
+.div-server {
+ background-color: #f9fff8;
+ border: 1px solid #ddd;
+ width: 25em;
+ padding: 20px;
+ margin: 20px;
+ margin-bottom: 0;
+ margin-top: 13px;
+ display: block;
+ float: left;
+}
+.server-name {
+ padding-bottom: 5px;
+ font-size: 1.4em;
+ color: #5d9ceb;
+}
+.server-status {
+ border-radius: 50% 50%;
+ width: 10px;
+ height: 10px;
+ display: inline-block;
+ margin-left: 2px;
+ margin-bottom: -2px;
+}
+.server-action {
+ float: right;
+ margin-top: 6px;
+}
+.server-desc {
+ padding-bottom: 2em;
+ color: #999;
+}
+.server-act-links a {
+ margin-right: 0.36em !important
+}
+.server-act-links a:last-child {
+ margin-right: 0 !important;
+}
+.ajax-server {
+ margin: 25px;
+ margin-left: 32em;
+ margin-bottom: 0;
+ width: 60em;
+ display: none;
+ margin-top: px;
+ margin-bottom: 0px;
+ margin-top: 14px;
+ height: 11em;
+}
+.haproxy-info {
+ display: inline-block;
+ width: 160px;
+ padding-left: 20px;
+ padding-top: 1.1em;
+ font-size: 0.88em;
+}
+.top-info {
+ display: inline-block;
+ width: 350px;
+}
\ No newline at end of file