Commit f387bc28 authored by Stavros Sachtouris's avatar Stavros Sachtouris Committed by Giorgos Korfiatis
Browse files

Implement a "status" command to showcase CLI cmds

parent cfa26bea
......@@ -13,11 +13,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from ws4py.client import WebSocketBaseClient
import cmd
import sys
import logging
from agkyra import config
from agkyra import config, protocol, protocol_client
LOG = logging.getLogger(__name__)
......@@ -101,9 +100,21 @@ class ConfigCommands:
self.cnf.write()
class AgkyraCLI(cmd.Cmd, WebSocketBaseClient):
class AgkyraCLI(cmd.Cmd):
"""The CLI for Agkyra is connected to a protocol server"""
cnf_cmds = ConfigCommands()
helper = protocol.SessionHelper()
@property
def client(self):
"""Return the helper client instace or None"""
self._client = getattr(self, '_client', None)
if not self._client:
session = self.helper.load_active_session()
if session:
self._client = protocol_client.UIClient(session)
self._client.connect()
return self._client
def preloop(self):
"""Prepare agkyra shell"""
......@@ -185,6 +196,21 @@ class AgkyraCLI(cmd.Cmd, WebSocketBaseClient):
except AttributeError:
self.do_help('config')
def do_status(self, line):
"""Get Agkyra client status. Status may be one of the following:
Up and syncing There is a process syncing right now
Up and paused Notifiers are active but syncing is paused
Not running No active processes
"""
client = self.client
if client:
# Ask the server for the status
status = client.get_status()
msg = 'paused' if status['paused'] else 'running'
sys.stdout.write('Up and %s\n' % msg)
else:
sys.stdout.write('Not running\n')
sys.stdout.flush()
# AgkyraCLI().run_onecmd(sys.argv)
......
#!/usr/bin/env python
# Copyright (C) 2015 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
......@@ -133,7 +131,7 @@ class SessionHelper(object):
class WebSocketProtocol(WebSocket):
"""Helper-side WebSocket protocol for communication with GUI:
-- INTERRNAL HANDSAKE --
-- INTERNAL HANDSAKE --
GUI: {"method": "post", "ui_id": <GUI ID>}
HELPER: {"ACCEPTED": 202, "action": "post ui_id"}" or
"{"REJECTED": 401, "action": "post ui_id"}
......@@ -424,11 +422,16 @@ class WebSocketProtocol(WebSocket):
self.heart.start()
def closed(self, *args):
"""Stop server heart, empty DB and exit"""
LOG.debug('Stop protocol heart')
"""When a connection closes"""
LOG.debug('Stop protocol heart for this session')
self.heart.stop()
def shutdown(self):
"""Shutdown the service"""
self.close()
LOG.debug('Clean database')
self.clean_db()
Thread(target=self.server.shutdown).start()
def clean_db(self):
"""Clean DB from session traces"""
......@@ -453,8 +456,7 @@ class WebSocketProtocol(WebSocket):
self.syncer.stop_all_daemons()
LOG.debug('Wait open syncs to complete')
self.syncer.wait_sync_threads()
self.close()
Thread(target=self.server.shutdown).start()
self.shutdown()
return
{
'start': self.start_sync,
......@@ -465,7 +467,7 @@ class WebSocketProtocol(WebSocket):
self.accepted = True
self.send_json({'ACCEPTED': 202, 'action': 'post ui_id'})
self._load_settings()
if self.can_sync():
if (not self.syncer) and self.can_sync():
self.init_sync()
self.start_sync()
else:
......
# Copyright (C) 2015 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from ws4py.client.threadedclient import WebSocketClient
import json
import time
import logging
LOG = logging.getLogger(__name__)
class UIClient(WebSocketClient):
"""W Web Socket Client for Agkyra"""
buf, authenticated, ready = {}, False, False
def __init__(self, session):
self.ui_id = session['ui_id']
super(UIClient, self).__init__(session['address'])
def opened(self):
"""On connection, authenticate or close"""
if self.ui_id:
self.send(json.dumps(dict(method='post', ui_id=self.ui_id)))
else:
self.close()
def closed(self, code, reason):
"""After the client is closed"""
LOG.debug('Client exits with %s, %s' % code, reason)
def wait_until_ready(self, timeout=20):
"""Wait until client is connected"""
while not self.ready:
time.sleep(1)
assert self.ready, 'UI client timed out while waiting to be ready'
return self.ready
def received_message(self, m):
"""handle server responces according to the protocol"""
msg = json.loads('%s' % m)
{
'post ui_id': self.recv_authenticate,
'get status': self.recv_get_status
}[msg['action']](msg)
# Request handlers
def send_get_status(self):
"""Request: GET STATUS"""
self.send(json.dumps(dict(method='get', path='status')))
# Receive handlers
def recv_authenticate(self, msg):
"""Receive: client authentication response"""
assert 'ACCEPTED' in msg, json.dumps(msg)
self.ready = True
def recv_get_status(self, msg):
"""Receive: GET STATUS"""
assert 'can_sync' in msg, json.dumps(msg)
self.buf[msg['action']] = msg
# API methods
def get_status(self):
"""Ask server for status, return status"""
self.wait_until_ready()
self.send_get_status()
while 'get status' not in self.buf:
time.sleep(1)
return self.buf.pop('get status')
......@@ -34,7 +34,7 @@ FORMATTER = logging.Formatter(
"[CLI]%(name)s %(levelname)s:%(asctime)s:%(message)s")
HANDLER.setFormatter(FORMATTER)
LOGGER.addHandler(HANDLER)
LOGGER.setLevel(logging.DEBUG)
LOGGER.setLevel(logging.INFO)
def main():
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment