Skip to content

Commit

Permalink
CTERA Messaging service (#169)
Browse files Browse the repository at this point in the history
cterasdk/core/messaging.py
cterasdk/tests/ut/test_core_messaging.py
cterasdk/docs/source/user_guides/Portal/GlobalAdmin.rst
  • Loading branch information
Elchay-Levy committed Nov 20, 2022
1 parent 5276a5f commit 5640b18
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 5 deletions.
3 changes: 2 additions & 1 deletion cterasdk/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
'cloudfs',
'zones',
'files',
'decorator'
'decorator',
'messaging'
]
54 changes: 54 additions & 0 deletions cterasdk/core/messaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import logging

from .base_command import BaseCommand
from ..common import Object


class Messaging(BaseCommand):
"""
Portal Messaging Service Management APIs
"""

def is_active(self):
"""
Check if messaging service is Active
"""
return self._portal.get('/microservices/messaging/globalStatus').status == 'Active'

def get_status(self):
"""
Retrieve the global status of messaging service
"""
res = self._portal.get('/microservices/messaging/globalStatus')
return res

def get_servers_status(self):
"""
Retrieve the status of the messaging servers
"""
return {f'{srv.server.name}: "{srv.serverStatus.status}"' for srv in self._portal.get('/microservices/messaging').currentNodes}

def add(self, servers):
"""
Add messaging servers to cluster
:param list[str] servers: Server names (number of allowed servers: 1 or 3)
"""
nodes = []
messaging_obj = self._portal.get('/microservices/messaging')
if messaging_obj.globalStatus.canAddServers:
for node in messaging_obj.availableNodes:
if node.server.name in servers and node.canAssignAsMessaging.allowed:
param = Object()
param._class = 'CurrentMessagingNode' # pylint: disable=protected-access
param.server = node.server
nodes.append(param)
if len(nodes) in messaging_obj.globalStatus.validServerNumber:
response = self._portal.put('microservices/messaging/currentNodes', nodes)
logging.getLogger().info('Nodes added to cluster successfully')
return response
logging.getLogger().error('Wrong number of servers. expected:"1" or "3", %s', {'given': len(servers)})
else:
logging.getLogger().error('Can not add new servers: %s', {messaging_obj.globalStatus.cantAddServersReason})
return None
2 changes: 1 addition & 1 deletion cterasdk/object/Agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ..edge import uri


class Agent(CTERAHost):
class Agent(CTERAHost): # pylint: disable=too-many-instance-attributes
"""
Main class operating on a Agent
Expand Down
9 changes: 6 additions & 3 deletions cterasdk/object/Portal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from ..client import CTERAHost, authenticated
from ..core import connection
from ..core import connection, messaging
from ..core import activation
from ..core import antivirus
from ..core import buckets
Expand Down Expand Up @@ -167,7 +167,7 @@ def iterator(self, path, param):
return query.iterator(self, path, param)


class GlobalAdmin(Portal):
class GlobalAdmin(Portal): # pylint: disable=too-many-instance-attributes
"""
Main class for Global Admin operations on a Portal
Expand All @@ -179,6 +179,8 @@ class GlobalAdmin(Portal):
:ivar cterasdk.core.syslog.Syslog syslog: Object holding the Portal syslog APIs
:ivar cterasdk.core.antivirus.Antivirus antivirus: Object holding the Portal Antivirus APIs
:ivar cterasdk.core.buckets.Buckets buckets: Object holding the Portal Storage Node APIs
:ivar cterasdk.core.messaging.Messaging messaging: Object holding the Portal Messaging Service Management APIs
"""

def __init__(self, host, port=None, https=True):
Expand All @@ -196,10 +198,11 @@ def __init__(self, host, port=None, https=True):
self.syslog = syslog.Syslog(self)
self.antivirus = antivirus.Antivirus(self)
self.buckets = buckets.Buckets(self)
self.messaging = messaging.Messaging(self)

@property
def _omit_fields(self):
return super()._omit_fields + ['portals', 'servers', 'setup', 'ssl', 'startup', 'syslog', 'antivirus', 'buckets']
return super()._omit_fields + ['portals', 'servers', 'setup', 'ssl', 'startup', 'syslog', 'antivirus', 'buckets', 'messaging']

@property
def context(self):
Expand Down
30 changes: 30 additions & 0 deletions docs/source/user_guides/Portal/GlobalAdmin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,36 @@ Servers
admin.servers.modify('server2', enable_public_ip=True, public_ip='33.191.55.2') # configure a public NAT ip address
Messaging Service
-----------------
.. automethod:: cterasdk.core.messaging.Messaging.get_status
:noindex:

.. code-block:: python
"""Retrieve the global status of Messaging service"""
print(admin.messaging.get_status())
.. automethod:: cterasdk.core.messaging.Messaging.get_servers_status
:noindex:

.. code-block:: python
"""Retrieve the status of the Messaging servers"""
print(admin.messaging.get_servers_status())
.. automethod:: cterasdk.core.messaging.Messaging.add
:noindex:

.. code-block:: python
"""Add Messaging servers to cluster"""
servers = ["server1", "server2", "server3"]
admin.messaging.add(servers)
Antivirus
---------

Expand Down
63 changes: 63 additions & 0 deletions tests/ut/test_core_messaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from unittest import mock

from cterasdk.common import Object
from cterasdk.core import messaging
from tests.ut import base_core


class TestCoreMessaging(base_core.BaseCoreTest):

def setUp(self):
super().setUp()
self._servers = ["server1", "server2", "server3"]
self._messaging = Object()

self._messaging.globalStatus = Object()
self._messaging.globalStatus._class = "GlobalMessagingStatus" # pylint: disable=protected-access
self._messaging.globalStatus.status = "Active"
self._messaging.globalStatus.canAddServers = True
self._messaging.globalStatus.cantAddServersReason = ""
self._messaging.globalStatus.validServerNumber = [1, 3]

self._messaging.availableNodes = []
self._messaging.currentNodes = []
for server in self._servers:
_node = Object()
_node._class = "MessagingServerCandidate" # pylint: disable=protected-access
_node.canAssignAsMessaging = Object()
_node.canAssignAsMessaging.allowed = True
_node.server = Object()
_node.server.name = server
self._messaging.availableNodes.append(_node)

def test_status(self):
self._init_global_admin(get_response=self._messaging.globalStatus)
ret = messaging.Messaging(self._global_admin).get_status()
self._global_admin.get.assert_called_once_with('/microservices/messaging/globalStatus')
self.assertEqual(ret, self._messaging.globalStatus)

def test_is_active(self):
self._init_global_admin(get_response=self._messaging.globalStatus)
messaging.Messaging(self._global_admin).is_active()
self._global_admin.get.assert_called_once_with('/microservices/messaging/globalStatus')

def test_add_server(self):
self._init_global_admin(get_response=self._messaging)
messaging.Messaging(self._global_admin).add(self._servers)
self._global_admin.get.assert_called_once_with('/microservices/messaging')
self._global_admin.put.assert_called_once_with('microservices/messaging/currentNodes', mock.ANY)
expected_param = self._get_current_node_objects()
actual_param = self._global_admin.put.call_args[0][1]
self._assert_equal_objects(actual_param, expected_param)

def _get_current_node_objects(self):
nodes = []
for node in self._messaging.availableNodes:
current_node_object = Object()
current_node_object._class = "CurrentMessagingNode" # pylint: disable=protected-access
current_node_object.server = node.server
current_node_object.serverStatus = Object()
current_node_object.serverStatus.status = "Running"
current_node_object.serverStatus._class = "MessagingServerStatus" # pylint: disable=protected-access
nodes.append(current_node_object)
return nodes

0 comments on commit 5640b18

Please sign in to comment.