diff --git a/SoftLayer/CLI/monitor/__init__.py b/SoftLayer/CLI/monitor/__init__.py new file mode 100644 index 000000000..c2a201acc --- /dev/null +++ b/SoftLayer/CLI/monitor/__init__.py @@ -0,0 +1 @@ +"""Monitoring""" diff --git a/SoftLayer/CLI/monitor/status.py b/SoftLayer/CLI/monitor/status.py new file mode 100644 index 000000000..ec622abec --- /dev/null +++ b/SoftLayer/CLI/monitor/status.py @@ -0,0 +1,82 @@ +""" +usage: sl monitor [] [...] [options] + +Manage Monitoring. + +The available commands are: + status Show basic monitoring status of servers +""" + +import click + +import SoftLayer +from SoftLayer.CLI import environment +from SoftLayer.CLI import formatting +from SoftLayer import utils + + +@click.command() +@click.option('--only_hardware', is_flag=True, + help="Show only physical servers") +@click.option('--only_virtual', is_flag=True, + help="Show only virtual servers") +@environment.pass_env +def cli(env, only_hardware=False, only_virtual=False): + """shows SERVER_PING status of all servers.""" + + table = formatting.Table([ + 'id', 'datacenter', 'FQDN', 'IP', + 'status', 'Type', 'last checked at' + ]) + hw_manager = SoftLayer.HardwareMonitorManager(env.client) + vs_manager = SoftLayer.VSMonitorManager(env.client) + if only_virtual: + hardware = [] + guest = vs_manager.list_status() + elif only_hardware: + hardware = hw_manager.list_status() + guest = [] + else: + hardware = hw_manager.list_status() + guest = vs_manager.list_status() + + results = hardware + guest + for server_object in results: + server = utils.NestedDict(server_object) + for monitor in server['networkMonitors']: + try: + res = monitor['lastResult']['responseStatus'] + date = monitor['lastResult']['finishTime'] + ip_address = monitor['ipAddress'] + monitor_type = monitor['queryType']['name'] + except KeyError: + # if a monitor does't have the lastResult ususally it is + # still being provisioned + res = 0 + date = "--" + ip_address = None + monitor_type = "--" + + status = 'UNKNOWN' + status_color = None + if res == 0: + status = 'DOWN' + status_color = 'red' + elif res == 1: + status = 'WARNING' + status_color = 'yellow' + elif res == 2: + status = 'OK' + status_color = 'green' + + table.add_row([ + server['id'], + server['datacenter']['name'] or formatting.blank(), + server['fullyQualifiedDomainName'], + ip_address or formatting.blank(), + click.style(status, fg=status_color), + monitor_type, + date + ]) + + return table diff --git a/SoftLayer/CLI/routes.py b/SoftLayer/CLI/routes.py index 676757384..a7f223a59 100644 --- a/SoftLayer/CLI/routes.py +++ b/SoftLayer/CLI/routes.py @@ -125,6 +125,9 @@ ('metadata', 'SoftLayer.CLI.metadata:cli'), + ('monitor', 'SoftLayer.CLI.monitor'), + ('monitor:status', 'SoftLayer.CLI.monitor.status:cli'), + ('nas', 'SoftLayer.CLI.nas'), ('nas:list', 'SoftLayer.CLI.nas.list:cli'), ('nas:credentials', 'SoftLayer.CLI.nas.credentials:cli'), diff --git a/SoftLayer/managers/__init__.py b/SoftLayer/managers/__init__.py index 4acfc325f..b2ad30300 100644 --- a/SoftLayer/managers/__init__.py +++ b/SoftLayer/managers/__init__.py @@ -18,6 +18,8 @@ from SoftLayer.managers.load_balancer import LoadBalancerManager # NOQA from SoftLayer.managers.messaging import MessagingManager # NOQA from SoftLayer.managers.metadata import MetadataManager # NOQA +from SoftLayer.managers.monitor.hw_monitor import HardwareMonitorManager # NOQA +from SoftLayer.managers.monitor.vs_monitor import VSMonitorManager # NOQA from SoftLayer.managers.network import NetworkManager # NOQA from SoftLayer.managers.ordering import OrderingManager # NOQA from SoftLayer.managers.sshkey import SshKeyManager # NOQA @@ -30,4 +32,5 @@ 'MetadataManager', 'CDNManager', 'NetworkManager', 'SshKeyManager', 'SSLManager', 'TicketManager', 'VSManager', 'ISCSIManager', 'LoadBalancerManager', - 'OrderingManager'] + 'OrderingManager', 'HardwareMonitorManager', + 'VSMonitorManager'] diff --git a/SoftLayer/managers/monitor/__init__.py b/SoftLayer/managers/monitor/__init__.py new file mode 100644 index 000000000..2d7c460c5 --- /dev/null +++ b/SoftLayer/managers/monitor/__init__.py @@ -0,0 +1,6 @@ +""" + SoftLayer.managers.monitor + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" diff --git a/SoftLayer/managers/monitor/hw_monitor.py b/SoftLayer/managers/monitor/hw_monitor.py new file mode 100644 index 000000000..784a7d67e --- /dev/null +++ b/SoftLayer/managers/monitor/hw_monitor.py @@ -0,0 +1,40 @@ +""" + SoftLayer.monitor.hw_monitor + ~~~~~~~~~~~~~~~~~~ + Monitoring Manager/helpers for Hardware_Server + + :license: MIT, see LICENSE for more details. +""" + + +class HardwareMonitorManager(object): + """Manages monitoring for Hardware Servers + + :param SoftLayer.API.CLient client: an API client instance + """ + + def __init__(self, client): + self.client = client + self.account = self.client['Account'] + self.server = self.client['Hardware_Server'] + + def list_status(self, **kwargs): + """List all hardware with their monitoring status + + :param dict \\*\\*kwargs: response-level options (mask, limit, filter) + :returns: Retrns a list of dictionaries with server and monitoring + information. + """ + + vs_items = [ + 'id', + 'fullyQualifiedDomainName', + 'primaryBackendIpAddress', + 'primaryIpAddress', + 'datacenter', + 'networkMonitors[lastResult,queryType]' + ] + + kwargs['mask'] = ('[mask[%s]]' + % (','.join(vs_items))) + return self.account.call('getHardware', **kwargs) diff --git a/SoftLayer/managers/monitor/vs_monitor.py b/SoftLayer/managers/monitor/vs_monitor.py new file mode 100644 index 000000000..f1f9d084a --- /dev/null +++ b/SoftLayer/managers/monitor/vs_monitor.py @@ -0,0 +1,40 @@ +""" + SoftLayer.monitor.vs_monitor + ~~~~~~~~~~~~~~~~~~ + Monitoring Manager/helpers for Virtual_Guest + + :license: MIT, see LICENSE for more details. +""" + + +class VSMonitorManager(object): + """Manages monitoring for Virtual Servers + + :param SoftLayer.API.CLient client: an API client instance + """ + + def __init__(self, client): + self.client = client + self.account = self.client['Account'] + self.server = self.client['Virtual_Guest'] + + def list_status(self, **kwargs): + """List all virtual guests with their monitoring status + + :param dict \\*\\*kwargs: response-level options (mask, limit, filter) + :returns: Retrns a list of dictionaries with server and monitoring + information. + """ + + vs_items = [ + 'id', + 'fullyQualifiedDomainName', + 'primaryBackendIpAddress', + 'primaryIpAddress', + 'datacenter', + 'networkMonitors[lastResult,queryType]' + ] + + kwargs['mask'] = ('[mask[%s]]' + % (','.join(vs_items))) + return self.account.call('getVirtualGuests', **kwargs) diff --git a/SoftLayer/testing/fixtures/Monitor.py b/SoftLayer/testing/fixtures/Monitor.py new file mode 100644 index 000000000..e69de29bb diff --git a/SoftLayer/testing/fixtures/SoftLayer_Account.py b/SoftLayer/testing/fixtures/SoftLayer_Account.py index 3701cbd7e..81675afe0 100644 --- a/SoftLayer/testing/fixtures/SoftLayer_Account.py +++ b/SoftLayer/testing/fixtures/SoftLayer_Account.py @@ -31,7 +31,6 @@ 'globalIdentifier': '1a2b3c-1701', 'primaryBackendIpAddress': '10.45.19.37', 'hourlyBillingFlag': False, - 'billingItem': { 'id': 6327, 'recurringFee': 1.54, @@ -43,6 +42,24 @@ } } }, + 'networkMonitors': [{ + 'guestId': 100, + 'hardwareId': '', + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 2, + 'finishTime': '2015-01-28T17:27:06-06:00' + } + }, { + 'guestId': 104, + 'hardwareId': '', + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'KEY_ERROR'}, + 'lastResult': { + 'responseStatus': 1 + } + }], }, { 'id': 104, 'hostname': 'vs-test2', @@ -69,6 +86,25 @@ } } }, + 'networkMonitors': [{ + 'guestId': 104, + 'hardwareId': '', + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 0, + 'finishTime': '2014-01-28T17:27:06-06:00' + } + }, { + 'guestId': 104, + 'hardwareId': '', + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 1, + 'finishTime': '2014-01-28T17:27:06-06:00' + } + }], }] getMonthlyVirtualGuests = [vs for vs in getVirtualGuests @@ -136,7 +172,17 @@ 'friendlyName': 'Friendly Transaction Name', 'id': 6660 } - } + }, + 'networkMonitors': [{ + 'guestId': '', + 'hardwareId': 1000, + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 1, + 'finishTime': '2014-01-28T17:27:06-06:00' + } + }], }, { 'id': 1001, 'globalIdentifier': '1a2b3c-1702', @@ -180,7 +226,17 @@ 'vlanNumber': 3672, 'id': 19082 }, - ] + ], + 'networkMonitors': [{ + 'guestId': '', + 'hardwareId': 1001, + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 0, + 'finishTime': '2014-01-28T17:27:06-06:00' + } + }], }, { 'id': 1002, 'datacenter': {'name': 'TEST00', @@ -223,7 +279,17 @@ 'vlanNumber': 3672, 'id': 19082 }, - ] + ], + 'networkMonitors': [{ + 'guestId': '', + 'hardwareId': 1002, + 'ipAddress': '158.85.177.200', + 'queryType': {'name': 'SERVICE_PING'}, + 'lastResult': { + 'responseStatus': 2, + 'finishTime': '2014-01-28T17:27:06-06:00' + } + }], }] getDomains = [{'name': 'example.com', 'id': 12345, diff --git a/SoftLayer/tests/CLI/modules/monitor_tests.py b/SoftLayer/tests/CLI/modules/monitor_tests.py new file mode 100644 index 000000000..13fe3eb79 --- /dev/null +++ b/SoftLayer/tests/CLI/modules/monitor_tests.py @@ -0,0 +1,31 @@ +""" + SoftLayer.tests.managers.monitor_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" +import SoftLayer +from SoftLayer import testing + + +class MonitorTests(testing.TestCase): + + def set_up(self): + self.hw_monitor_manager = SoftLayer.HardwareMonitorManager(self.client) + self.vs_monitor_manager = SoftLayer.VSMonitorManager(self.client) + + def test_list_status(self): + result = self.run_command(['monitor', 'status']) + self.assertEqual(result.exit_code, 0) + self.assert_called_with('SoftLayer_Account', 'getVirtualGuests') + self.assert_called_with('SoftLayer_Account', 'getHardware') + + def test_list_only_hardware(self): + result = self.run_command(['monitor', 'status', '--only_hardware']) + self.assert_called_with('SoftLayer_Account', 'getHardware') + self.assertEqual(result.exit_code, 0) + + def test_list_only_virtual(self): + result = self.run_command(['monitor', 'status', '--only_virtual']) + self.assert_called_with('SoftLayer_Account', 'getVirtualGuests') + self.assertEqual(result.exit_code, 0) diff --git a/SoftLayer/tests/managers/monitor_tests.py b/SoftLayer/tests/managers/monitor_tests.py new file mode 100644 index 000000000..469ae000e --- /dev/null +++ b/SoftLayer/tests/managers/monitor_tests.py @@ -0,0 +1,26 @@ +""" + SoftLayer.tests.managers.monitor_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" +import SoftLayer +from SoftLayer import testing +from SoftLayer.testing import fixtures + + +class MonitorTests(testing.TestCase): + + def set_up(self): + self.hw_monitor_manager = SoftLayer.HardwareMonitorManager(self.client) + self.vs_monitor_manager = SoftLayer.VSMonitorManager(self.client) + + def test_list_hardware_status(self): + result = self.hw_monitor_manager.list_status() + self.assertEqual(result, fixtures.SoftLayer_Account.getHardware) + self.assert_called_with('SoftLayer_Account', 'getHardware') + + def test_list_guest_status(self): + result = self.vs_monitor_manager.list_status() + self.assertEqual(result, fixtures.SoftLayer_Account.getVirtualGuests) + self.assert_called_with('SoftLayer_Account', 'getVirtualGuests')