Skip to content
This repository has been archived by the owner on Mar 2, 2022. It is now read-only.

Commit

Permalink
Added service CLI base class
Browse files Browse the repository at this point in the history
  • Loading branch information
Lorenzo Delgado committed Jun 7, 2018
1 parent b7b584d commit a584117
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 21 deletions.
13 changes: 8 additions & 5 deletions nssm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
__copyright__ = metadata.copyright


from .service import Service, ServiceStatus # NOQA
from .configuration import ServiceConfiguration # NOQA
from .parameters import StartupType, PriorityLevel, ServiceType, ExitAction # NOQA
from .exceptions import * # NOQA
from .service import Service, ServiceStatus
from .configuration import ServiceConfiguration
from .parameters import StartupType, PriorityLevel, ServiceType, ExitAction
from .exceptions import *

# Service CLI base class
from .cli import ServiceCliCommand

# NSSM executable path
from .wrapper import executable # NOQA
from .wrapper import executable
225 changes: 225 additions & 0 deletions nssm/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
"""
Created on June 7, 2018
@author: Lorenzo Delgado <[email protected]>
"""
from inspect import isclass
from argparse import ArgumentParser, Namespace, _SubParsersAction


class CliCommand(object):
"""
Command line command class
"""

def __init__(self, parser):
"""
:param parser: Root argument parser or "command" sub-parser
:type parser: :class:`.ArgumentParser` or :class:`._SubParsersAction`
"""

# Check parser type to avoid undesired exceptions from
# :class:`.ArgumentParser`.
if isinstance(parser, ArgumentParser):
self.subparsers = parser.add_subparsers(dest="command")
elif isinstance(parser, _SubParsersAction):
self.subparsers = parser
else:
msg = "Invalid input argument type: {}"
raise TypeError(msg.format(parser))

@staticmethod
def execute(args):
"""
Execute the desired command actions
:param args: Command line parsed arguments
:type args: :class:`.Namespace`
"""
pass


class ServiceCliCommand(CliCommand):
"""
Service command line base class
Extend this class to add custom arguments to the different commands
"""

SERVICE = None

def __init__(self, parser, service=None):
"""
:param parser: Root argument parser
:type parser: :class:`.ArgumentParser` or :class:`._SubParsersAction`
:param service: Nssm service class
:type service: :class:`type` or :class:`nssm.Service`
"""

if service:
self.SERVICE = service

# Check parser type to avoid undesired exceptions from `argparser`.
super(ServiceCliCommand, self).__init__(parser)

# Service command
service_parser = self.subparsers.add_parser("service")
self.add_service_arguments(service_parser)

# Service actions
service_subparsers = service_parser.add_subparsers(dest="action")

# Service action: "install"
service_install_parser = service_subparsers.add_parser("install")
self.add_service_install_arguments(service_install_parser)

# Service action: "uninstall"
service_remove_parser = service_subparsers.add_parser("remove")
service_uninstall_parser = service_subparsers.add_parser("uninstall")
self.add_service_uninstall_arguments(service_remove_parser)
self.add_service_uninstall_arguments(service_uninstall_parser)

# Service action: "start"
service_start_parser = service_subparsers.add_parser("start")
self.add_service_start_arguments(service_start_parser)

# Service action: "restart"
service_restart_parser = service_subparsers.add_parser("restart")
self.add_service_restart_arguments(service_restart_parser)

# Service action: "stop"
service_stop_parser = service_subparsers.add_parser("stop")
self.add_service_stop_arguments(service_stop_parser)

# Service action: "pause"
service_pause_parser = service_subparsers.add_parser("pause")
self.add_service_pause_arguments(service_pause_parser)

# Service action: "resume"
service_resume_parser = service_subparsers.add_parser("resume")
self.add_service_resume_arguments(service_resume_parser)

# Service action: "status"
service_status_parser = service_subparsers.add_parser("status")
self.add_service_status_arguments(service_status_parser)

# Service action: "configure"
service_configure_parser = service_subparsers.add_parser("configure")
self.add_service_configure_arguments(service_configure_parser)

# Service action: "edit"
service_edit_parser = service_subparsers.add_parser("edit")
service_nssm_parser = service_subparsers.add_parser("nssm")

def add_service_arguments(self, parser):
"""
Override this method to add arguments to service command.
:param parser: Argument parser for service command.
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_install_arguments(self, parser):
"""
Override this method to add arguments to service command's "install"
action.
:param parser: Argument parser for service "install" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_uninstall_arguments(self, parser):
"""
Override this method to add arguments to service command's
"uninstall" action.
:param parser: Argument parser for service "uninstall" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_start_arguments(self, parser):
"""
Override this method to add arguments to service command's "start"
action.
:param parser: Argument parser for service "start" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_restart_arguments(self, parser):
"""
Override this method to add arguments to service command's "restart"
action.
:param parser: Argument parser for service "restart" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_stop_arguments(self, parser):
"""
Override this method to add arguments to service command's "stop"
action.
:param parser: Argument parser for service "stop" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_pause_arguments(self, parser):
"""
Override this method to add arguments to service command's "pause"
action.
:param parser: Argument parser for service "pause" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_resume_arguments(self, parser):
"""
Override this method to add arguments to service command's "resume"
action.
:param parser: Argument parser for service "resume" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_status_arguments(self, parser):
"""
Override this method to add arguments to service command's "status"
action.
:param parser: Argument parser for service "status" action
:type parser: :class:`.ArgumentParser`
"""
pass

def add_service_configure_arguments(self, parser):
"""
Override this method to add arguments to service command's
"configure" action.
:param parser: Argument parser for service "configure" action
:type parser: :class:`.ArgumentParser`
"""
pass

@classmethod
def edit(cls):
"""
Default implementation for "service edit/nssm" action
"""
if cls.SERVICE:
if isclass(cls.SERVICE):
cls.SERVICE()._edit()
else:
cls.SERVICE._edit()
else:
msg = 'Service not associated: {}'
raise AttributeError(msg.format(cls.SERVICE))

2 changes: 1 addition & 1 deletion nssm/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
package = 'pynssm'
project = "PyNSSM"
project_no_spaces = project.replace(' ', '')
version = '2.24.1-alpha.3'
version = '2.24.2-alpha.1'
description = "Python wrapper for NSSM - the Non-Sucking Service Manager (nssm.cc)" # NOQA
authors = ['Lorenzo Delgado']
authors_string = ', '.join(authors)
Expand Down
46 changes: 31 additions & 15 deletions nssm/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,29 @@ class Service(object):
NSSM Service class
"""

def __init__(self, name, path, **kwargs):
SERVICE_NAME = None
SERVICE_PATH = None

def __init__(self, name=None, path=None, **kwargs):
"""
:param name: Service name
:type name: :class:`str`
:param path: Executable path
:type path: :class:`str`
"""
self.name = name
self.path = path
if name:
self.SERVICE_NAME = name

if path:
self.SERVICE_PATH = path

self.configuration = ServiceConfiguration(**kwargs)

def install(self):
"""
Install the service
"""
Wrapper.command("install", self.name, self.path)
Wrapper.command("install", self.SERVICE_NAME, self.SERVICE_PATH)

if self.configuration:
self.configure(self.configuration)
Expand All @@ -44,37 +51,37 @@ def remove(self):
"""
Remove the service
"""
Wrapper.command("remove", self.name, "confirm")
Wrapper.command("remove", self.SERVICE_NAME, "confirm")

def start(self):
"""
Start the service
"""
Wrapper.command("start", self.name)
Wrapper.command("start", self.SERVICE_NAME)

def stop(self):
"""
Stop the service
"""
Wrapper.command("stop", self.name)
Wrapper.command("stop", self.SERVICE_NAME)

def restart(self):
"""
Restart the service
"""
Wrapper.command("restart", self.name)
Wrapper.command("restart", self.SERVICE_NAME)

def pause(self):
"""
Pause the service
"""
Wrapper.command("pause", self.name)
Wrapper.command("pause", self.SERVICE_NAME)

def resume(self):
"""
Resume the service
"""
Wrapper.command("continue", self.name)
Wrapper.command("continue", self.SERVICE_NAME)

def rotate(self):
"""
Expand All @@ -85,15 +92,16 @@ def rotate(self):
file rotation. Non-nssm services might respond to control 128 in
their own way (or ignore it, or crash).
"""
Wrapper.command("rotate", self.name)
Wrapper.command("rotate", self.SERVICE_NAME)

def status(self):
"""
Query the service's status
:return: Service status
:rtype: :class:`ServiceStatus`
:rtype: :class:`.ServiceStatus`
"""
rc, out = Wrapper.command("status", self.name)
rc, out = Wrapper.command("status", self.SERVICE_NAME)
return ServiceStatus(out.strip())

def configure(self, config):
Expand Down Expand Up @@ -123,14 +131,22 @@ def configure(self, config):
elif param == "action_on_exit":
for k, v in value.items():
v = v.value
Wrapper.command("set", self.name, PARAM_MAP[param], k, v)
Wrapper.command("set", self.SERVICE_NAME, PARAM_MAP[param], k, v)
continue

if isinstance(value, AbstractEnum):
value = value.value
elif isinstance(value, bool):
value = 1 if value else 0

Wrapper.command("set", self.name, PARAM_MAP[param], value)
Wrapper.command("set", self.SERVICE_NAME, PARAM_MAP[param], value)

def _edit(self):
"""
Opens the NSSM in GUI mode to edit the configured service. Intended
to be called only from the CLI.
:param name: Service name
:type name: :class:`str`
"""
Wrapper.command("edit", self.SERVICE_NAME)

0 comments on commit a584117

Please sign in to comment.