aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdi Feschiyan <edi.feschiyan@konsulko.com>2020-08-31 16:06:02 +0300
committerEdi Feschiyan <efeschiyan@pm.me>2020-08-31 16:06:02 +0300
commit9b622d79f69efa4c21fa9156744b8e0e2eee1229 (patch)
treea8c273eea0b1f4dd0d7d1cba8a990175327c0154
parent4a763058a63b6d1574958847898fe22a6cc0a62c (diff)
mediascanner service is not running in the system on boot, so adding runafmservice and startsystemdservice methods and adjusting the portfinder() to run the missing service.
-rw-r--r--pyagl/services/base.py90
-rw-r--r--pyagl/services/mediascanner.py6
-rw-r--r--pyagl/tests/test_mediascanner.py2
3 files changed, 78 insertions, 20 deletions
diff --git a/pyagl/services/base.py b/pyagl/services/base.py
index 0ffbcde..40f7640 100644
--- a/pyagl/services/base.py
+++ b/pyagl/services/base.py
@@ -21,6 +21,7 @@ from random import randint
from enum import IntEnum
from typing import Union
import asyncssh
+from asyncssh import SSHClientConnection
import argparse
import asyncio
import binascii
@@ -29,7 +30,6 @@ import json
import sys
import os
import re
-
# logging.getLogger('AGLBaseService')
# logging.basicConfig(level=logging.DEBUG)
@@ -43,7 +43,7 @@ class AFBT(IntEnum):
msgq = {}
-AFBLEN = 3
+AFBLEN = 3 # usual AppFrameworkBinder responses/events have 3 items in the list - [messagetype, sessionid, payload]
def newrand():
@@ -133,7 +133,7 @@ class AGLBaseService:
return parser
def __init__(self, api: str, ip: str, port: str = None, url: str = None,
- token: str = 'HELLO', uuid: str = 'magic', service: str = None):
+ token: str = 'HELLO', uuid: str = 'magic', service: str = None, runservice: bool = False):
self.api = api
self.url = url
self.ip = ip
@@ -141,6 +141,7 @@ class AGLBaseService:
self.token = token
self.uuid = uuid
self.service = service
+ self.runsvc = runservice
self.logger = logging.getLogger(service)
def __await__(self):
@@ -153,7 +154,7 @@ class AGLBaseService:
# setting ping_timeout to None because AFB does not support websocket ping
# if set to !None, the library will close the socket after the default timeout
if self.port is None:
- serviceport = await self.portfinder()
+ serviceport = await self.portfinder(runservice=self.runsvc)
if serviceport is not None:
self.port = serviceport
else:
@@ -178,7 +179,7 @@ class AGLBaseService:
async def receive(self):
return await self.websocket.recv()
- async def portfinder(self):
+ async def portfinder(self, runservice=False):
fieldsstr = '{sl}: {local_address} {rem_address} {st} {tx_queue}:{rx_queue} {tr}:{tmwhen} {retrnsmt} {uid}' \
' {timeout} {inode} {sref_cnt} {memloc} {rto} {pred_sclk} {ackquick} {congest} {slowstart}'
# TODO:handle ssh timeouts, asyncssh does not support it apparently, and connect returns context_manager which
@@ -187,13 +188,26 @@ class AGLBaseService:
servicename = check_output(f"systemctl --all | grep {self.service}-- | awk '{{print $1}}'".encode(), shell=True)
servicename = servicename.decode().strip()
if self.service not in servicename:
- self.logger.error(f"Service matching pattern - '{self.service}' - NOT FOUND")
- exit(1)
+ if runservice:
+ await self.runafmservice()
+ servicename = await check_output(f"systemctl --all | grep {self.service}-- | awk '{{print $1}}'",
+ shell=True) # retry getting service name after starting
+ servicename = servicename.decode().strip()
+ else:
+ self.logger.error(f"Service matching pattern - '{self.service}' - NOT FOUND")
+ exit(1)
pid = check_output(f'systemctl show --property MainPID --value {servicename}'.encode(), shell=True)
pid = int(pid.decode().strip(), 10)
- if pid == 0:
+ if pid == 0 and servicename != '':
self.logger.warning(f'Service {servicename} is stopped')
- return None
+ if runservice:
+ self.logger.warning(f' Trying to start service {servicename}')
+ await self.startsystemdservice(servicename=servicename)
+ pid = check_output(f'systemctl show --property MainPID --value {servicename}', shell=True)
+ pid = int(pid.stdout.strip(), 10)
+
+ else:
+ return None
else:
self.logger.debug(f'Service PID: {str(pid)}')
@@ -208,14 +222,27 @@ class AGLBaseService:
else:
async with asyncssh.connect(self.ip, username='root') as c:
servicename = await c.run(f"systemctl --all | grep {self.service}-- | awk '{{print $1}}'", check=False)
- if self.service not in servicename.stdout:
- self.logger.error(f"Service matching pattern - '{self.service}' - NOT FOUND")
- exit(1)
- pidres = await c.run(f'systemctl show --property MainPID --value {servicename.stdout.strip()}')
+ servicename = servicename.stdout.strip()
+ if self.service not in servicename:
+ if runservice:
+ await self.runafmservice(connection=c)
+ servicename = await c.run(f"systemctl --all | grep {self.service}-- | awk '{{print $1}}'",
+ check=False) # retry getting service name after starting
+ servicename = servicename.stdout.strip()
+ else:
+ self.logger.error(f"Service matching pattern - '{self.service}' - NOT FOUND")
+ exit(1)
+ pidres = await c.run(f'systemctl show --property MainPID --value {servicename}')
pid = int(pidres.stdout.strip(), 10)
- if pid == 0:
- self.logger.warning(f'Service {servicename.stdout.strip()} is stopped')
- return None
+ if pid == 0 and servicename != '':
+ self.logger.warning(f'Service {servicename} is stopped')
+ if runservice:
+ self.logger.warning(f' Trying to start service {servicename}')
+ await self.startsystemdservice(servicename=servicename, connection=c)
+ pidres = await c.run(f'systemctl show --property MainPID --value {servicename}')
+ pid = int(pidres.stdout.strip(), 10)
+ else:
+ return None
else:
self.logger.debug(f'Service PID: {str(pid)}')
@@ -250,6 +277,37 @@ class AGLBaseService:
self.logger.debug(f'Service running at port {port}')
return port
+ async def runafmservice(self, servicename: str = None, connection: SSHClientConnection = None):
+ name = servicename if servicename is not None else self.service
+ pid = None
+ result = None
+ if self.ip == '127.0.0.1' or self.ip == 'localhost': # running locally, ssh not needed
+ result = check_output(f'afm-util start {name}', shell=True).decode().strip()
+ else: # running remotely
+ if connection is not None:
+ result = await connection.run(f'afm-util start {self.service}')
+ result = result.stdout.strip()
+ else:
+ self.logger.error('Trying to start service remotely but no SSHClientConnection given')
+
+ if result.isnumeric:
+ self.logger.debug(f'Started service via afm-util, PID: {result}')
+ pid = int(result)
+ else:
+ self.logger.error(f'Unable to start service via afm-util: {result}')
+
+ return pid
+
+ @staticmethod
+ async def startsystemdservice(servicename: str, connection: SSHClientConnection = None):
+ result = None
+ if connection is not None:
+ result = await connection.run(f'systemctl start {servicename}')
+ result = result.stdout.strip()
+ else:
+ result = check_output(f'systemctl start {servicename}', shell=True)
+ print(result)
+
async def listener(self, stdout: bool = False):
while True:
raw = await self.response()
diff --git a/pyagl/services/mediascanner.py b/pyagl/services/mediascanner.py
index e3016ec..b40457f 100644
--- a/pyagl/services/mediascanner.py
+++ b/pyagl/services/mediascanner.py
@@ -21,12 +21,12 @@ verbs = ['subscribe', 'unsubscribe', 'media_result']
class MediaScannerService(AGLBaseService):
- service = 'service-mediascanner'
+ service = 'agl-service-mediascanner'
parser = AGLBaseService.getparser()
parser.add_argument('--media_result', help='Query media_results verb', action='store_true')
- def __init__(self, ip, port=None, service='service-mediascanner'):
- super().__init__(api='mediascanner', ip=ip, port=port, service=service)
+ def __init__(self, ip, port=None, service='agl-service-mediascanner', runservice=True):
+ super().__init__(api='mediascanner', ip=ip, port=port, service=service, runservice=runservice)
# more init stuff specific to the new service
async def media_result(self):
diff --git a/pyagl/tests/test_mediascanner.py b/pyagl/tests/test_mediascanner.py
index a4d57ee..9aba4b0 100644
--- a/pyagl/tests/test_mediascanner.py
+++ b/pyagl/tests/test_mediascanner.py
@@ -33,7 +33,7 @@ def event_loop():
async def service():
address = os.environ.get('AGL_TGT_IP', 'localhost')
port = os.environ.get('AGL_TGT_PORT', None)
- ns = await mss(ip=address, port=port)
+ ns = await mss(ip=address, port=port, runservice=True)
yield ns
await ns.websocket.close()