Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support for Service tool added. #3573

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 100 additions & 1 deletion lisa/base_tools/service.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
import re
from typing import Type
from enum import Enum
from time import sleep
from typing import Optional, Type

from lisa.executable import ExecutableResult, Tool
from lisa.tools.powershell import PowerShell
from lisa.util import (
LisaException,
UnsupportedDistroException,
create_timer,
filter_ansi_escape,
find_group_in_lines,
)
Expand All @@ -25,6 +30,10 @@ def command(self) -> str:
def can_install(self) -> bool:
return False

@classmethod
def _windows_tool(cls) -> Optional[Type[Tool]]:
return WindowsService

def _check_exists(self) -> bool:
cmd_result = self.node.execute(
"ls -lt /run/systemd/system", shell=True, sudo=True
Expand Down Expand Up @@ -200,3 +209,93 @@ def _check_service_running(self, name: str) -> bool:

def _check_error_codes(cmd_result: ExecutableResult, error_code: int = 0) -> None:
cmd_result.assert_exit_code(expected_exit_code=[0, error_code])


class WindowsServiceStatus(int, Enum):
CONTINUE_PENDING = 5
PAUSE_PENDING = 6
PAUSED = 7
RUNNING = 4
START_PENDING = 2
STOP_PENDING = 3
STOPPED = 1
NOT_FOUND = 0


class WindowsService(Tool):
@property
def can_install(self) -> bool:
return False

@property
def command(self) -> str:
return ""

def enable_service(self, name: str) -> None:
pass

def restart_service(self, name: str, ignore_exit_code: int = 0) -> None:
self.node.tools[PowerShell].run_cmdlet(
f"Restart-service {name}",
force_run=True,
)
self.wait_for_service_start(name)

def stop_service(self, name: str) -> None:
self.node.tools[PowerShell].run_cmdlet(
f"Stop-Service {name} -Force",
force_run=True,
output_json=True,
fail_on_error=False,
)
self.wait_for_service_stop(name)

def wait_for_service_start(self, name: str) -> None:
squirrelsc marked this conversation as resolved.
Show resolved Hide resolved
self._wait_for_service(name, WindowsServiceStatus.RUNNING)

def wait_for_service_stop(self, name: str) -> None:
self._wait_for_service(name, WindowsServiceStatus.STOPPED)

def _check_exists(self) -> bool:
return True

def check_service_exists(self, name: str) -> bool:
if (
self._get_status(name, fail_on_error=False)
== WindowsServiceStatus.NOT_FOUND
):
return False
squirrelsc marked this conversation as resolved.
Show resolved Hide resolved
return True

def _get_status(
self, name: str = "", fail_on_error: bool = True
) -> WindowsServiceStatus:
try:
service_status = self.node.tools[PowerShell].run_cmdlet(
f"Get-Service {name}",
force_run=True,
output_json=True,
)
return WindowsServiceStatus(int(service_status["Status"]))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this line to the end of the method, so it's easy to read.

except LisaException as identifier:
if "Cannot find any service with service name" in str(identifier):
if fail_on_error:
raise LisaException(f"service '{name}' does not exist")
return WindowsServiceStatus.NOT_FOUND
raise identifier

def _wait_for_service(self, name: str, status: WindowsServiceStatus) -> None:
timeout = 60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the timeout to a parameter. 30 seconds should be enough.

timer = create_timer()
self._log.debug(f"waiting for service '{name}' to be in '{status}' state")
while timeout > timer.elapsed(False):
current_service_status = self._get_status(name)
if status == current_service_status:
return
sleep(0.5)

if timeout < timer.elapsed():
raise LisaException(
f"service '{name}' still in '{current_service_status}' state"
f"after '{timeout}' seconds"
)
Loading