mirror of
https://github.com/itsdave-de/msp.git
synced 2025-06-28 08:54:04 +02:00
Merge pull request #16 from itsdave-de/feature/add-host-status-information-to-it-object
Feature/add host status information to it object
This commit is contained in:
commit
b5388517c0
@ -2,7 +2,144 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('IT Object', {
|
frappe.ui.form.on('IT Object', {
|
||||||
refresh: function(frm) {
|
refresh: function (frm) {
|
||||||
|
|
||||||
|
const loader = `
|
||||||
|
<div class="line-wobble"></div>
|
||||||
|
<style>
|
||||||
|
.line-wobble {
|
||||||
|
--uib-size: 80px;
|
||||||
|
--uib-speed: 1.75s;
|
||||||
|
--uib-color: black;
|
||||||
|
--uib-line-weight: 5px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
top: 45%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: var(--uib-line-weight);
|
||||||
|
width: var(--uib-size);
|
||||||
|
border-radius: calc(var(--uib-line-weight) / 2);
|
||||||
|
overflow: hidden;
|
||||||
|
transform: translate3d(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-wobble::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--uib-color);
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-wobble::after {
|
||||||
|
content: '';
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: calc(var(--uib-line-weight) / 2);
|
||||||
|
animation: wobble var(--uib-speed) ease-in-out infinite;
|
||||||
|
transform: translateX(-95%);
|
||||||
|
background-color: var(--uib-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes wobble {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateX(-95%);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateX(95%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const container = document.getElementById('oitc-output');
|
||||||
|
|
||||||
|
// Set width and height to <div> parent element and to <form> grandparent element so relative width and height with % works greate
|
||||||
|
container.parentElement.parentElement.style.width = '100%';
|
||||||
|
container.parentElement.parentElement.style.height = '100%';
|
||||||
|
container.parentElement.style.width = '100%';
|
||||||
|
container.parentElement.style.height = '90%';
|
||||||
|
|
||||||
|
// Set this styles to showcase where the information will appear
|
||||||
|
container.style.width = '100%';
|
||||||
|
container.style.height = '100%';
|
||||||
|
container.style.background = 'rgba(212, 204, 203, 0.4)';
|
||||||
|
container.innerHTML = loader;
|
||||||
|
|
||||||
|
frm.call('get_oitc_host_status_data', {})
|
||||||
|
.then((response) => {
|
||||||
|
const container = document.getElementById('oitc-output');
|
||||||
|
|
||||||
|
if (response.message.status !== 200) {
|
||||||
|
container.innerHTML = response.message.response || 'An error occurred while fetching OITC data';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let background = response.message?.statusColors?.upStateColor;
|
||||||
|
if (response.message?.host?.hostStatus?.currentState?.toUpperCase() === "DOWN") {
|
||||||
|
background = response.message?.statusColors?.downStateColor;
|
||||||
|
} else if (response.message?.host?.hostStatus?.currentState?.toUpperCase() === "UNREACHABLE") {
|
||||||
|
background = response.message?.statusColors?.unreachableStateColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.innerHTML = `
|
||||||
|
<div class="js-oitc-output">
|
||||||
|
<div>
|
||||||
|
<h1 class="font-size-50" style="color: white;">
|
||||||
|
${response.message?.host?.hostStatus?.currentState?.toUpperCase()}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Current State since</div>
|
||||||
|
<h3 style="color: white; margin: 1rem 0;">
|
||||||
|
${response.message?.host?.hostStatus?.currentStateSince}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Last check</div>
|
||||||
|
<h3 style="color: white; margin: 1rem 0;">
|
||||||
|
${response.message?.host?.hostStatus?.lastCheck}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Next check</div>
|
||||||
|
<h3 style="color: white; margin: 1rem 0;">
|
||||||
|
${response.message?.host?.hostStatus?.nextCheck}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>Services</div>
|
||||||
|
<h3 style="color: white; margin: 1rem 0;">
|
||||||
|
Total Services: ${response.message?.host?.servicesStatus?.totalServices}
|
||||||
|
</h3>
|
||||||
|
<div>Services Status:</div>
|
||||||
|
<h3 style="color: white; margin: 1rem 0;">
|
||||||
|
<ul style="text-align:left;">
|
||||||
|
<li>OK: ${response.message?.host?.servicesStatus?.state?.ok}</li>
|
||||||
|
<li>CRITICAL: ${response.message?.host?.servicesStatus?.state?.critical}</li>
|
||||||
|
<li>WARNING: ${response.message?.host?.servicesStatus?.state?.warning}</li>
|
||||||
|
<li>UNKNOWN: ${response.message?.host?.servicesStatus?.state?.unknown}</li>
|
||||||
|
</ul>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
let statusData = document.querySelector('.js-oitc-output')
|
||||||
|
statusData.style.textAlign = 'center';
|
||||||
|
statusData.style.color = '#FFF';
|
||||||
|
statusData.style.fontWeight = 'Bold';
|
||||||
|
statusData.style.background = background;
|
||||||
|
statusData.style.padding = '1rem';
|
||||||
|
})
|
||||||
|
|
||||||
if (frm.doc.admin_interface_link) {
|
if (frm.doc.admin_interface_link) {
|
||||||
frm.add_custom_button('Open Admin Interface', () => frm.trigger('open_admin_interface'), 'Actions');
|
frm.add_custom_button('Open Admin Interface', () => frm.trigger('open_admin_interface'), 'Actions');
|
||||||
};
|
};
|
||||||
@ -10,10 +147,10 @@ frappe.ui.form.on('IT Object', {
|
|||||||
frm.add_custom_button('Open Monitoring', () => frm.trigger('open_monitoring'), 'Actions');
|
frm.add_custom_button('Open Monitoring', () => frm.trigger('open_monitoring'), 'Actions');
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
open_admin_interface: function(frm) {
|
open_admin_interface: function (frm) {
|
||||||
window.open(frm.doc.admin_interface_link, '_blank').focus();
|
window.open(frm.doc.admin_interface_link, '_blank').focus();
|
||||||
},
|
},
|
||||||
open_monitoring: function(frm) {
|
open_monitoring: function (frm) {
|
||||||
window.open(frm.doc.monitoring_link, '_blank').focus();
|
window.open(frm.doc.monitoring_link, '_blank').focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
"customer",
|
"customer",
|
||||||
"it_landscape",
|
"it_landscape",
|
||||||
"location",
|
"location",
|
||||||
|
"monitoring_section",
|
||||||
|
"oitc_output",
|
||||||
"description_section",
|
"description_section",
|
||||||
"description",
|
"description",
|
||||||
"image",
|
"image",
|
||||||
@ -143,11 +145,22 @@
|
|||||||
"fieldname": "oitc_host_uuid",
|
"fieldname": "oitc_host_uuid",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "OITC Host UUID"
|
"label": "OITC Host UUID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "monitoring_section",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"label": "Monitoring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "oitc_output",
|
||||||
|
"fieldtype": "HTML",
|
||||||
|
"label": "OITC Output",
|
||||||
|
"options": "<div id=\"oitc-output\">OITC output expected</div>"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-07-18 10:24:39.463386",
|
"modified": "2022-07-18 15:05:40.504305",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "MSP",
|
"module": "MSP",
|
||||||
"name": "IT Object",
|
"name": "IT Object",
|
||||||
|
@ -3,8 +3,74 @@
|
|||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
# import frappe
|
import frappe
|
||||||
|
import requests
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class ITObject(Document):
|
class ITObject(Document):
|
||||||
pass
|
|
||||||
|
def get_host_status_from_hosts_data(self, hosts_data, msp_settings_doc):
|
||||||
|
|
||||||
|
host_data_response = {}
|
||||||
|
|
||||||
|
for host_data in hosts_data['all_hosts']:
|
||||||
|
|
||||||
|
if host_data['Host']['uuid'] != self.oitc_host_uuid:
|
||||||
|
continue
|
||||||
|
|
||||||
|
host_data_response = {
|
||||||
|
'status': 200,
|
||||||
|
'host': {
|
||||||
|
'id': host_data['Host']['id'],
|
||||||
|
'uuid': host_data['Host']['uuid'],
|
||||||
|
'hostStatus': {
|
||||||
|
'currentState': host_data['Hoststatus']['humanState'],
|
||||||
|
'lastCheck': host_data['Hoststatus']['lastCheckInWords'],
|
||||||
|
'nextCheck': host_data['Hoststatus']['nextCheckInWords'],
|
||||||
|
'currentStateSince': host_data['Hoststatus']['lastHardStateChangeInWords']
|
||||||
|
},
|
||||||
|
'servicesStatus': {
|
||||||
|
'totalServices': host_data['ServicestatusSummary']['total'],
|
||||||
|
'state': {
|
||||||
|
'ok': host_data['ServicestatusSummary']['state']['ok'],
|
||||||
|
'critical': host_data['ServicestatusSummary']['state']['critical'],
|
||||||
|
'unknown': host_data['ServicestatusSummary']['state']['unknown'],
|
||||||
|
'warning': host_data['ServicestatusSummary']['state']['warning']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'statusColors': {
|
||||||
|
'upStateColor': msp_settings_doc.oitc_status_up_color,
|
||||||
|
'downStateColor': msp_settings_doc.oitc_status_down_color,
|
||||||
|
'unreachableStateColor': msp_settings_doc.oitc_status_unreachable_color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return host_data_response
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_oitc_host_status_data(self):
|
||||||
|
msp_settings_doc = frappe.get_doc('MSP Settings')
|
||||||
|
|
||||||
|
if not self.oitc_host_uuid:
|
||||||
|
return {
|
||||||
|
'status': 422,
|
||||||
|
'response': "This host does not have any OITC Host UUID stored. Please store an OITC Host UUID in the 'External References' section to get its status data."
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
endpoint = f'{msp_settings_doc.oitc_url}hosts/index.json?angular=true&scroll=true&page=1'
|
||||||
|
api_authorization = f'{msp_settings_doc.oitc_api_key_header_string}' + msp_settings_doc.get_password('oitc_api_key')
|
||||||
|
headers = {'Authorization': api_authorization}
|
||||||
|
|
||||||
|
hosts_data = requests.get(url=endpoint, headers=headers, verify=False)
|
||||||
|
|
||||||
|
return self.get_host_status_from_hosts_data(hosts_data.json(), msp_settings_doc)
|
||||||
|
except Exception as exception:
|
||||||
|
exception_message = f'Data could not be fetched from {msp_settings_doc.oitc_url}. Error -> {str(exception)}'
|
||||||
|
|
||||||
|
return {
|
||||||
|
'status': 500,
|
||||||
|
'response': exception_message
|
||||||
|
}
|
||||||
|
@ -8,7 +8,12 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"open_it_cockpit_integration_section",
|
"open_it_cockpit_integration_section",
|
||||||
"oitc_url",
|
"oitc_url",
|
||||||
|
"oitc_api_key_header_string",
|
||||||
"oitc_api_key",
|
"oitc_api_key",
|
||||||
|
"column_break_column",
|
||||||
|
"oitc_status_up_color",
|
||||||
|
"oitc_status_down_color",
|
||||||
|
"oitc_status_unreachable_color",
|
||||||
"qr_code_settings_section",
|
"qr_code_settings_section",
|
||||||
"qr_code_dark_color",
|
"qr_code_dark_color",
|
||||||
"qr_code_scale"
|
"qr_code_scale"
|
||||||
@ -27,7 +32,8 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "oitc_api_key",
|
"fieldname": "oitc_api_key",
|
||||||
"fieldtype": "Password",
|
"fieldtype": "Password",
|
||||||
"label": "OITC API Key"
|
"label": "OITC API Key",
|
||||||
|
"length": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "qr_code_settings_section",
|
"fieldname": "qr_code_settings_section",
|
||||||
@ -43,12 +49,40 @@
|
|||||||
"fieldname": "qr_code_scale",
|
"fieldname": "qr_code_scale",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "QR Code Scale"
|
"label": "QR Code Scale"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "X-OITC-API ",
|
||||||
|
"fieldname": "oitc_api_key_header_string",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"label": "OITC API Key Header string",
|
||||||
|
"length": 100,
|
||||||
|
"options": "X-OITC-API "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_column",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"label": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "oitc_status_up_color",
|
||||||
|
"fieldtype": "Color",
|
||||||
|
"label": "OITC Status Up Color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "oitc_status_down_color",
|
||||||
|
"fieldtype": "Color",
|
||||||
|
"label": "OITC Status Down Color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "oitc_status_unreachable_color",
|
||||||
|
"fieldtype": "Color",
|
||||||
|
"label": "OITC Status Unreachable Color"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-07-18 10:53:35.413597",
|
"modified": "2022-07-19 12:16:04.805493",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "MSP",
|
"module": "MSP",
|
||||||
"name": "MSP Settings",
|
"name": "MSP Settings",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user