Skip to content

Commit

Permalink
discovery, powerOn, powerOff, powerCycle functionality was added
Browse files Browse the repository at this point in the history
  • Loading branch information
alexquali committed Jan 25, 2024
1 parent 5c08012 commit 7de4a35
Show file tree
Hide file tree
Showing 32 changed files with 26,293 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
types: [ published ]
jobs:
tox-ci:
uses: QualiSystems/.github/.github/workflows/package-tox-py-37-39.yml@master
uses: QualiSystems/.github/.github/workflows/package-tox-py-39.yml@master
pypi-deploy:
needs: tox-ci
uses: QualiSystems/.github/.github/workflows/package-deploy-pypi.yml@master
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/github-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- master
jobs:
tox-ci:
uses: QualiSystems/.github/.github/workflows/package-tox-py-37-39.yml@master
uses: QualiSystems/.github/.github/workflows/package-tox-py-39.yml@master
pypi-deploy:
needs: tox-ci
uses: QualiSystems/.github/.github/workflows/package-github-release.yml@master
2 changes: 1 addition & 1 deletion .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ on:
- master
jobs:
tox-ci:
uses: QualiSystems/.github/.github/workflows/package-tox-py-37-39.yml@master
uses: QualiSystems/.github/.github/workflows/package-tox-py-39.yml@master
13 changes: 2 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ repos:
hooks:
- id: pyupgrade
args:
- "--py37-plus"
- "--py39-plus"
- repo: https://github.com/timothycrosley/isort
rev: 5.12.0
hooks:
- id: isort
exclude: '/mibs'
- repo: https://github.com/python/black
rev: 23.3.0
rev: 22.12.0
hooks:
- id: black
exclude: '/mibs'
Expand All @@ -27,13 +27,4 @@ repos:
flake8-eradicate,
flake8-requirements,
]
args: [
"--known-modules=cloudshell-template:[cloudshell.template],cloudshell-shell-core:[cloudshell.shell.core]"
]
exclude: '/mibs'
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.1.1
hooks:
- id: mypy
additional_dependencies: [types-attrs]
exclude: ^tests/
File renamed without changes.
3 changes: 3 additions & 0 deletions cloudshell/raritan/autoload/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
25,658 changes: 25,658 additions & 0 deletions cloudshell/raritan/autoload/mibs/PDU2-MIB.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions cloudshell/raritan/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
70 changes: 70 additions & 0 deletions cloudshell/raritan/cli/raritan_cli_configurator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from __future__ import annotations

import logging
from collections.abc import Collection
from typing import TYPE_CHECKING, ClassVar

from attrs import define, field
from typing_extensions import Self

from cloudshell.cli.configurator import AbstractModeConfigurator
from cloudshell.cli.factory.session_factory import (
CloudInfoAccessKeySessionFactory,
ConsoleSessionFactory,
GenericSessionFactory,
SessionFactory,
)
from cloudshell.cli.service.command_mode_helper import CommandModeHelper
from cloudshell.cli.session.console_ssh import ConsoleSSHSession
from cloudshell.cli.session.console_telnet import ConsoleTelnetSession
from cloudshell.cli.session.ssh_session import SSHSession
from cloudshell.cli.session.telnet_session import TelnetSession

from cloudshell.raritan.cli.raritan_command_modes import (
ConfigCommandMode,
EnableCommandMode,
)

if TYPE_CHECKING:
from cloudshell.cli.service.cli import CLI
from cloudshell.cli.types import T_COMMAND_MODE_RELATIONS, CliConfigProtocol


@define
class RaritanCliConfigurator(AbstractModeConfigurator):
REGISTERED_SESSIONS: ClassVar[tuple[SessionFactory]] = (
CloudInfoAccessKeySessionFactory(SSHSession),
GenericSessionFactory(TelnetSession),
ConsoleSessionFactory(ConsoleSSHSession),
ConsoleSessionFactory(
ConsoleTelnetSession, session_kwargs={"start_with_new_line": False}
),
ConsoleSessionFactory(
ConsoleTelnetSession, session_kwargs={"start_with_new_line": True}
),
)
modes: T_COMMAND_MODE_RELATIONS = field(init=False)

def __attrs_post_init__(self):
super().__attrs_post_init__()
self.modes = CommandModeHelper.create_command_mode(self._auth)

@classmethod
def from_config(
cls,
conf: CliConfigProtocol,
logger: logging.Logger | None = None,
cli: CLI | None = None,
registered_sessions: Collection[SessionFactory] | None = None,
) -> Self:
if not logger:
logger = logging.getLogger(__name__)
return super().from_config(conf, logger, cli, registered_sessions)

@property
def enable_mode(self):
return self.modes[EnableCommandMode]

@property
def config_mode(self):
return self.modes[ConfigCommandMode]
44 changes: 44 additions & 0 deletions cloudshell/raritan/cli/raritan_command_modes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from cloudshell.cli.service.command_mode import CommandMode

if TYPE_CHECKING:
from cloudshell.cli.service.auth_model import Auth


class EnableCommandMode(CommandMode):
PROMPT: str = r"(?:(?!\)).)#\s*$"
ENTER_COMMAND: str = ""
EXIT_COMMAND: str = ""

def __init__(self, auth: Auth):
"""Initialize Default command mode."""
self._auth = auth
CommandMode.__init__(
self,
EnableCommandMode.PROMPT,
EnableCommandMode.ENTER_COMMAND,
EnableCommandMode.EXIT_COMMAND,
)


class ConfigCommandMode(CommandMode):
PROMPT: str = r"config:#\s*$"
ENTER_COMMAND: str = "config"
EXIT_COMMAND: str = "apply" # Save changed settings and leave config mode

def __init__(self, auth: Auth):
"""Initialize Configuration command mode."""
self._auth = auth

CommandMode.__init__(
self,
ConfigCommandMode.PROMPT,
ConfigCommandMode.ENTER_COMMAND,
ConfigCommandMode.EXIT_COMMAND,
)


CommandMode.RELATIONS_DICT = {EnableCommandMode: {ConfigCommandMode: {}}}
3 changes: 3 additions & 0 deletions cloudshell/raritan/command_actions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
64 changes: 64 additions & 0 deletions cloudshell/raritan/command_actions/enable_disable_snmp_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from __future__ import annotations

from typing import TYPE_CHECKING, ClassVar

from attrs import define

from cloudshell.cli.command_template.command_template_executor import (
CommandTemplateExecutor,
)
from cloudshell.snmp.snmp_parameters import SNMPV3Parameters # noqa F401

from cloudshell.raritan.command_templates import snmp_configuration_templates

if TYPE_CHECKING:
from cloudshell.cli.service.cli_service import CliService


@define
class BaseSnmpActions:
_cli_service: CliService
SNMP_VERSION: ClassVar[str] = "snmp_version"

def enable_snmp(self) -> str:
"""Enable snmp."""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=snmp_configuration_templates.ENABLE_SNMP,
).execute_command(snmp_version=self.SNMP_VERSION)

def disable_snmp(self) -> str:
"""Disable snmp."""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=snmp_configuration_templates.DISABLE_SNMP,
).execute_command(snmp_version=self.SNMP_VERSION)

def commit(self) -> str:
"""Save changed settings and leave config mode."""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=snmp_configuration_templates.COMMIT,
).execute_command()


class EnableDisableSnmpV2Actions(BaseSnmpActions):
SNMP_VERSION: ClassVar[str] = "v1/v2c"

def set_snmp_ro_community(self, snmp_community):
"""Set read community."""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=snmp_configuration_templates.SET_RO_SNMP_COMMUNITY,
).execute_command(name=snmp_community)

def set_snmp_rw_community(self, snmp_community):
"""Set write community."""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=snmp_configuration_templates.SET_RW_SNMP_COMMUNITY,
).execute_command(name=snmp_community)


class EnableDisableSnmpV3Actions(BaseSnmpActions):
SNMP_VERSION: ClassVar[str] = "v3"
71 changes: 71 additions & 0 deletions cloudshell/raritan/command_actions/system_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import annotations

import re
from typing import TYPE_CHECKING

from attrs import define

from cloudshell.cli.command_template.command_template_executor import (
CommandTemplateExecutor,
)

from cloudshell.raritan.command_templates import system_templates

if TYPE_CHECKING:
from cloudshell.cli.service.cli_service import CliService


@define
class SystemActions:
_cli_service: CliService

def get_pdu_info(self) -> dict[str, str]:
"""Get information about outlets."""
pdu_info = {}
output = CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=system_templates.GET_PDU_INFO,
).execute_command()

match = re.search(
r"Model:\s+(?P<model>.+)\s+"
r"Firmware Version:\s+(?P<fw>.+)\s+"
r"Serial Number: \s+(?P<serial>\w+)",
output,
re.I,
)
if match:
pdu_info.update(
{
"model": match.groupdict()["model"],
"fw": match.groupdict()["fw"],
"serial": match.groupdict()["serial"],
}
)
return pdu_info

def get_outlets(self) -> dict[str, str]:
"""Get information about outlets."""
outlets_info = {}
output = CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=system_templates.GET_OUTLETS_INFO,
).execute_command()

for outlet_id, outlet_state in re.findall(
r"Outlet\s+(?P<outlet_id>\d+):\sPower state:\s+(?P<outlet_state>\w+)",
output,
):
outlets_info.update({outlet_id: outlet_state})

return outlets_info

def set_outlets_state(self, outlets: str, outlet_state: str) -> str:
"""Set outlets state.
Possible outlets states could be on/off/cycle.
"""
return CommandTemplateExecutor(
cli_service=self._cli_service,
command_template=system_templates.CHANGE_OUTLET_STATE,
).execute_command(outlet_ids=outlets, outlet_state=outlet_state)
3 changes: 3 additions & 0 deletions cloudshell/raritan/command_templates/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from __future__ import annotations

from cloudshell.cli.command_template.command_template import CommandTemplate

ENABLE_SNMP = CommandTemplate(
command="network services snmp {snmp_version} enable",
action_map={
r"Are you sure you want to enable it\? \[y/n\]": lambda session, logger: session.send_line( # noqa: E501
"y", logger
)
},
)

DISABLE_SNMP = CommandTemplate("network services snmp {snmp_version} disable")

SET_RO_SNMP_COMMUNITY = CommandTemplate(
command="network services snmp readCommunity {read_community}"
)

SET_RW_SNMP_COMMUNITY = CommandTemplate(
command="network services snmp writeCommunity {write_community}"
)

COMMIT = CommandTemplate(command="apply")
16 changes: 16 additions & 0 deletions cloudshell/raritan/command_templates/system_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from __future__ import annotations

from cloudshell.cli.command_template.command_template import CommandTemplate

GET_PDU_INFO = CommandTemplate(command="show pdu details")
GET_OUTLETS_INFO = CommandTemplate(command="show outlets")

CHANGE_OUTLET_STATE = CommandTemplate(
command="power outlets {outlet_ids} {outlet_state} /y",
action_map={r"\[y/n\]": lambda session, logger: session.send_line("y", logger)},
error_map={
"[Ii]nvalid outlet specified": "Invalid outlet specified.",
"[Oo]peration on/off/cycle": "Wrong outlet state provided. "
"Possible values: on/off/cycle",
},
)
3 changes: 3 additions & 0 deletions cloudshell/raritan/flows/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
Loading

0 comments on commit 7de4a35

Please sign in to comment.