From 2615359fc91fa168dbf5021ffcf6ae48d3db08f0 Mon Sep 17 00:00:00 2001 From: png2000 Date: Tue, 5 Jan 2021 15:56:44 +0100 Subject: [PATCH 1/3] initial zhone commit --- bootup/conf/bootstraps/create-zhone.sh | 81 +++++++++++++++++++ bootup/restapi.sh | 5 +- cli.py | 7 +- nesi/softbox/api/models/box_models.py | 2 +- nesi/softbox/api/models/port_models.py | 6 ++ nesi/softbox/api/schemas/box_schemas.py | 2 +- nesi/softbox/api/schemas/subrack_schemas.py | 2 + nesi/softbox/api/views/base_views.py | 1 + nesi/softbox/base_resources/box.py | 1 + nesi/zhone/api/__init__.py | 7 ++ nesi/zhone/api/schemas/__init__.py | 25 ++++++ nesi/zhone/api/schemas/zhone_box_schemas.py | 14 ++++ nesi/zhone/api/schemas/zhone_card_schemas.py | 14 ++++ nesi/zhone/api/schemas/zhone_port_schemas.py | 15 ++++ .../api/schemas/zhone_subrack_schemas.py | 14 ++++ nesi/zhone/zhone_resources/__init__.py | 2 +- nesi/zhone/zhone_resources/zhone_box.py | 15 +++- nesi/zhone/zhone_resources/zhone_card.py | 0 nesi/zhone/zhone_resources/zhone_port.py | 35 ++++++++ nesi/zhone/zhone_resources/zhone_subrack.py | 0 templates/Zhone/login/base/dslstatEmptyArg.j2 | 2 + .../Zhone/login/base/dslstatInvalidArg.j2 | 2 + templates/Zhone/login/base/dslstatTemplate.j2 | 66 +++++++++++++++ templates/Zhone/login/base/on_cycle.j2 | 1 + templates/Zhone/login/base/on_enter.j2 | 2 + templates/Zhone/login/on_enter.j2 | 1 + templates/Zhone/login/password.j2 | 2 + templates/Zhone/on_cycle.j2 | 1 + templates/Zhone/on_enter.j2 | 0 .../accessPoints/root/rootCommandProcessor.py | 7 +- vendors/Zhone/__init__.py | 7 ++ vendors/Zhone/baseCommandProcessor.py | 29 +++++++ vendors/Zhone/main.py | 60 ++++++++++++++ vendors/Zhone/rootCommandProcessor.py | 33 ++++++++ 34 files changed, 451 insertions(+), 10 deletions(-) create mode 100644 bootup/conf/bootstraps/create-zhone.sh create mode 100644 nesi/zhone/api/__init__.py create mode 100644 nesi/zhone/api/schemas/__init__.py create mode 100644 nesi/zhone/api/schemas/zhone_box_schemas.py create mode 100644 nesi/zhone/api/schemas/zhone_card_schemas.py create mode 100644 nesi/zhone/api/schemas/zhone_port_schemas.py create mode 100644 nesi/zhone/api/schemas/zhone_subrack_schemas.py create mode 100644 nesi/zhone/zhone_resources/zhone_card.py create mode 100644 nesi/zhone/zhone_resources/zhone_port.py create mode 100644 nesi/zhone/zhone_resources/zhone_subrack.py create mode 100644 templates/Zhone/login/base/dslstatEmptyArg.j2 create mode 100644 templates/Zhone/login/base/dslstatInvalidArg.j2 create mode 100644 templates/Zhone/login/base/dslstatTemplate.j2 create mode 100644 templates/Zhone/login/base/on_cycle.j2 create mode 100644 templates/Zhone/login/base/on_enter.j2 create mode 100644 templates/Zhone/login/on_enter.j2 create mode 100644 templates/Zhone/login/password.j2 create mode 100644 templates/Zhone/on_cycle.j2 create mode 100644 templates/Zhone/on_enter.j2 create mode 100644 vendors/Zhone/__init__.py create mode 100644 vendors/Zhone/baseCommandProcessor.py create mode 100644 vendors/Zhone/main.py create mode 100644 vendors/Zhone/rootCommandProcessor.py diff --git a/bootup/conf/bootstraps/create-zhone.sh b/bootup/conf/bootstraps/create-zhone.sh new file mode 100644 index 0000000..5532916 --- /dev/null +++ b/bootup/conf/bootstraps/create-zhone.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# This file is part of the NESi software. +# +# Copyright (c) 2020 +# Original Software Design by Ilya Etingof . +# +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst +# +# Example NESi REST API server bootstrapping +# +ENDPOINT=http://localhost:5000/nesi/v1 + +path="`dirname \"$0\"`" + +. $path/functions.sh + +# Create a network device (admin operation) +req='{ + "vendor": "Zhone", + "model": "Zhone-Gerät lol", + "version": "2500", + "description": "(Juan-)", + "hostname": "Zhone-Gerät lul", + "network_protocol": "telnet", + "network_address": "127.0.0.1", + "network_port": 9023, + "uuid": "7777", + "software_version": "juan" + }' + +box_id=$(create_resource "$req" $ENDPOINT/boxen) || exit 1 + +# Sessionmanager credentials +req='{ + "username": "admin", + "password": "secret" +}' + +admin_credential_id=$(create_resource "$req" $ENDPOINT/boxen/$box_id/credentials) + +# create a Subrack + +req='{ + "name": "1", + "description": "Juan Zhone" +}' + +subrack_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/subracks) + +# create a Card + +req='{ + "subrack_id": '$subrack_1', + "name": "1/1", + "product": "vdsl", + "description": "Karte von Juan" +}' + +card_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/cards) + +# create a Port + +req='{ + "card_id": '$card_1', + "name": "1/1/1/0", + "description": "Port von Juan", + "admin_state": "1", + "operational_state": "1", + "upLineRate": 5555, + "downLineRate": 4444, + "maxUpLineRate": 3333, + "maxDownLineRate": 2222 +}' + +port_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) \ No newline at end of file diff --git a/bootup/restapi.sh b/bootup/restapi.sh index 6d8dd93..a9fa5c1 100755 --- a/bootup/restapi.sh +++ b/bootup/restapi.sh @@ -181,7 +181,8 @@ if [ $recreate_db = "yes" ]; then #bash bootup/conf/bootstraps/create-box-port-vlan.sh #bash bootup/conf/bootstraps/create-alcatel-7360.sh #bash bootup/conf/bootstraps/create-huawei-5623.sh - bash bootup/conf/bootstraps/create-keymile-MG2500.sh + #bash bootup/conf/bootstraps/create-keymile-MG2500.sh + bash bootup/conf/bootstraps/create-zhone.sh fi if [ $alcatel_api = "yes" ]; then @@ -200,7 +201,7 @@ if [ $pbn_api = "yes" ]; then bash bootup/conf/bootstraps/create-alcatel-7360.sh #work_in_progress fi if [ $zhone_api = "yes" ]; then - bash bootup/conf/bootstraps/create-alcatel-7360.sh #work_in_progress + bash bootup/conf/bootstraps/create-zhone.sh #work_in_progress fi diff --git a/cli.py b/cli.py index a64a13a..6abf6f8 100644 --- a/cli.py +++ b/cli.py @@ -1,9 +1,10 @@ # This file is part of the NESi software. # # Copyright (c) 2020, inexio -# Janis Groß -# Philip Konrath -# Alexander Dincher +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß # # Ilya Etingof # diff --git a/nesi/softbox/api/models/box_models.py b/nesi/softbox/api/models/box_models.py index f4d3f9c..455f157 100644 --- a/nesi/softbox/api/models/box_models.py +++ b/nesi/softbox/api/models/box_models.py @@ -1,4 +1,4 @@ -# This file is part of the NESi software. + # This file is part of the NESi software. # # Copyright (c) 2020 # Original Software Design by Ilya Etingof . diff --git a/nesi/softbox/api/models/port_models.py b/nesi/softbox/api/models/port_models.py index 6ed09a0..da78916 100644 --- a/nesi/softbox/api/models/port_models.py +++ b/nesi/softbox/api/models/port_models.py @@ -331,3 +331,9 @@ class Port(db.Model): profile4_enable = db.Column(db.Boolean(), default=False) profile4_name = db.Column(db.String(), default='') profile_mode = db.Column(db.Enum('Priority', 'ElectricalLoopLength'), default=None) + + #Zhone + upLineRate = db.Column(db.Integer(), default=0) + downLineRate = db.Column(db.Integer(), default=0) + maxUpLineRate = db.Column(db.Integer(), default=0) + maxDownLineRate = db.Column(db.Integer(), default=0) diff --git a/nesi/softbox/api/schemas/box_schemas.py b/nesi/softbox/api/schemas/box_schemas.py index eb5b802..41e0e6d 100644 --- a/nesi/softbox/api/schemas/box_schemas.py +++ b/nesi/softbox/api/schemas/box_schemas.py @@ -38,7 +38,7 @@ class Meta: 'subracks', 'subrack_details', 'cards', 'ports', 'channels', 'service_ports', 'emus', 'onts', 'cpe_ports', 'routes', 'login_banner', 'vlan_interfaces', 'users', 'user_details', 'portgroupports', 'mgmt_cards', 'welcome_banner', 'last_login', 'last_logout', 'sntp_server_ip_address', 'timezone_offset', - 'net_mask', 'default_gateway', '_links') + 'net_mask', 'default_gateway', '_links', 'ont_ports', 'cpes') credentials = ma.Hyperlinks( {'_links': { diff --git a/nesi/softbox/api/schemas/subrack_schemas.py b/nesi/softbox/api/schemas/subrack_schemas.py index 7a6c773..7bf1672 100644 --- a/nesi/softbox/api/schemas/subrack_schemas.py +++ b/nesi/softbox/api/schemas/subrack_schemas.py @@ -51,3 +51,5 @@ class Meta: _links = ma.Hyperlinks( {'self': ma.URLFor('show_subracks', box_id='')}) + + diff --git a/nesi/softbox/api/views/base_views.py b/nesi/softbox/api/views/base_views.py index 4259e94..2ac1261 100644 --- a/nesi/softbox/api/views/base_views.py +++ b/nesi/softbox/api/views/base_views.py @@ -21,6 +21,7 @@ from nesi.alcatel.api.schemas import * from nesi.huawei.api.schemas import * from nesi.keymile.api.schemas import * +from nesi.zhone.api.schemas import * # important for other view classes from nesi.softbox.api import db diff --git a/nesi/softbox/base_resources/box.py b/nesi/softbox/base_resources/box.py index 006e1a5..e839600 100644 --- a/nesi/softbox/base_resources/box.py +++ b/nesi/softbox/base_resources/box.py @@ -7,6 +7,7 @@ # - Janis Groß # - Philip Konrath # - Alexander Dincher +# - Philipp-Noah Groß # # License: https://github.com/inexio/NESi/LICENSE.rst diff --git a/nesi/zhone/api/__init__.py b/nesi/zhone/api/__init__.py new file mode 100644 index 0000000..0342a16 --- /dev/null +++ b/nesi/zhone/api/__init__.py @@ -0,0 +1,7 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst \ No newline at end of file diff --git a/nesi/zhone/api/schemas/__init__.py b/nesi/zhone/api/schemas/__init__.py new file mode 100644 index 0000000..c168985 --- /dev/null +++ b/nesi/zhone/api/schemas/__init__.py @@ -0,0 +1,25 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from inspect import isclass +from pkgutil import iter_modules +from pathlib import Path +from importlib import import_module + +# iterate through the modules in the current package +package_dir = Path(__file__).resolve().parent +for (_, module_name, _) in iter_modules([package_dir]): + + # import the module and iterate through its attributes + module = import_module(f"{__name__}.{module_name}") + for attribute_name in dir(module): + attribute = getattr(module, attribute_name) + + if isclass(attribute): + # Add the class to this package's variables + globals()[attribute_name] = attribute \ No newline at end of file diff --git a/nesi/zhone/api/schemas/zhone_box_schemas.py b/nesi/zhone/api/schemas/zhone_box_schemas.py new file mode 100644 index 0000000..74dab06 --- /dev/null +++ b/nesi/zhone/api/schemas/zhone_box_schemas.py @@ -0,0 +1,14 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi.softbox.api.schemas.box_schemas import * + +class ZhoneBoxSchema(BoxSchema): + class Meta: + model = Box + fields = BoxSchema.Meta.fields # + ('', '', '', '') diff --git a/nesi/zhone/api/schemas/zhone_card_schemas.py b/nesi/zhone/api/schemas/zhone_card_schemas.py new file mode 100644 index 0000000..32a66ed --- /dev/null +++ b/nesi/zhone/api/schemas/zhone_card_schemas.py @@ -0,0 +1,14 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi.softbox.api.schemas.card_schemas import * + +class ZhoneCardSchema(CardSchema): + class Meta: + model = Card + fields = CardSchema.Meta.fields # + ('', '', '', '') diff --git a/nesi/zhone/api/schemas/zhone_port_schemas.py b/nesi/zhone/api/schemas/zhone_port_schemas.py new file mode 100644 index 0000000..56f088c --- /dev/null +++ b/nesi/zhone/api/schemas/zhone_port_schemas.py @@ -0,0 +1,15 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi.softbox.api.schemas.port_schemas import * + +class ZhonePortSchema(PortSchema): + class Meta: + model = Port + fields = PortSchema.Meta.fields + ('upLineRate', 'downLineRate', 'maxUpLineRate', 'maxDownLineRate') + diff --git a/nesi/zhone/api/schemas/zhone_subrack_schemas.py b/nesi/zhone/api/schemas/zhone_subrack_schemas.py new file mode 100644 index 0000000..64bd078 --- /dev/null +++ b/nesi/zhone/api/schemas/zhone_subrack_schemas.py @@ -0,0 +1,14 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi.softbox.api.schemas.subrack_schemas import * + +class ZhoneSubrackSchema(SubrackSchema): + class Meta: + model = Subrack + fields = SubrackSchema.Meta.fields # + ('', '', '', '') \ No newline at end of file diff --git a/nesi/zhone/zhone_resources/__init__.py b/nesi/zhone/zhone_resources/__init__.py index a9a2c5b..250684e 100644 --- a/nesi/zhone/zhone_resources/__init__.py +++ b/nesi/zhone/zhone_resources/__init__.py @@ -1 +1 @@ -__all__ = [] +__all__ = ["zhone_port", "zhone_card", "zhone_subrack"] diff --git a/nesi/zhone/zhone_resources/zhone_box.py b/nesi/zhone/zhone_resources/zhone_box.py index 744d68f..5673a11 100644 --- a/nesi/zhone/zhone_resources/zhone_box.py +++ b/nesi/zhone/zhone_resources/zhone_box.py @@ -7,11 +7,12 @@ # - Janis Groß # - Philip Konrath # - Alexander Dincher +# - Philipp-Noah Groß # # License: https://github.com/inexio/NESi/LICENSE.rst from nesi.zhone.zhone_resources import * -from nesi.softbox.base_resources import credentials +from nesi.softbox.base_resources import credentials, base from nesi.softbox.base_resources import route from nesi.softbox.base_resources.box import * @@ -25,6 +26,18 @@ class ZhoneBox(Box): :param identity: The identity of the System resource """ # Define Zhone Properties + @property + def credentials(self): + return credentials.CredentialsCollection( + self._conn, base.get_sub_resource_path_by( + self, 'credentials')) + + def get_port(self, field, value): + """Get specific port object.""" + return zhone_port.ZhonePortCollection( + self._conn, base.get_sub_resource_path_by(self, 'ports'), + params={field: value}).find_by_field_value(field, value) + class ZhoneBoxCollection(BoxCollection): diff --git a/nesi/zhone/zhone_resources/zhone_card.py b/nesi/zhone/zhone_resources/zhone_card.py new file mode 100644 index 0000000..e69de29 diff --git a/nesi/zhone/zhone_resources/zhone_port.py b/nesi/zhone/zhone_resources/zhone_port.py new file mode 100644 index 0000000..51c2656 --- /dev/null +++ b/nesi/zhone/zhone_resources/zhone_port.py @@ -0,0 +1,35 @@ +# This file is part of the NESi software. +# +# Copyright (c) 2020 +# Original Software Design by Ilya Etingof . +# +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß \ No newline at end of file diff --git a/templates/Zhone/login/base/on_enter.j2 b/templates/Zhone/login/base/on_enter.j2 new file mode 100644 index 0000000..e607b9b --- /dev/null +++ b/templates/Zhone/login/base/on_enter.j2 @@ -0,0 +1,2 @@ +You logged in successfully. + diff --git a/templates/Zhone/login/on_enter.j2 b/templates/Zhone/login/on_enter.j2 new file mode 100644 index 0000000..8d65370 --- /dev/null +++ b/templates/Zhone/login/on_enter.j2 @@ -0,0 +1 @@ +Password: diff --git a/templates/Zhone/login/password.j2 b/templates/Zhone/login/password.j2 new file mode 100644 index 0000000..a16fedb --- /dev/null +++ b/templates/Zhone/login/password.j2 @@ -0,0 +1,2 @@ +Login incorrect + diff --git a/templates/Zhone/on_cycle.j2 b/templates/Zhone/on_cycle.j2 new file mode 100644 index 0000000..2a6191f --- /dev/null +++ b/templates/Zhone/on_cycle.j2 @@ -0,0 +1 @@ +login as: diff --git a/templates/Zhone/on_enter.j2 b/templates/Zhone/on_enter.j2 new file mode 100644 index 0000000..e69de29 diff --git a/vendors/KeyMile/accessPoints/root/rootCommandProcessor.py b/vendors/KeyMile/accessPoints/root/rootCommandProcessor.py index 091b9aa..b9c5fb9 100644 --- a/vendors/KeyMile/accessPoints/root/rootCommandProcessor.py +++ b/vendors/KeyMile/accessPoints/root/rootCommandProcessor.py @@ -14,7 +14,6 @@ from nesi import exceptions from vendors.KeyMile.baseCommandProcessor import BaseCommandProcessor - class RootCommandProcessor(BaseCommandProcessor): __name__ = 'root' management_functions = {'main', 'cfgm', 'fm', 'status'} @@ -25,6 +24,12 @@ class RootCommandProcessor(BaseCommandProcessor): from .rootManagementFunctions import fm from .rootManagementFunctions import status + def do_get(self, command, *args, context=None): + if self._validate(args, "CurrTemperature"): + context['currTemperature'] = self._model.currTemperature + context['spacer'] = self.create_spacers((67,), (context['currTemperature'],))[0] * ' ' + self._write(self._render('currTemperature', 'login', 'base', 'get', context=context)) + def _init_access_points(self, context=None): self.access_points = ('eoam', 'fan', 'multicast', 'services', 'tdmConnections') for card in self._model.cards: diff --git a/vendors/Zhone/__init__.py b/vendors/Zhone/__init__.py new file mode 100644 index 0000000..0342a16 --- /dev/null +++ b/vendors/Zhone/__init__.py @@ -0,0 +1,7 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst \ No newline at end of file diff --git a/vendors/Zhone/baseCommandProcessor.py b/vendors/Zhone/baseCommandProcessor.py new file mode 100644 index 0000000..d80fd90 --- /dev/null +++ b/vendors/Zhone/baseCommandProcessor.py @@ -0,0 +1,29 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi import exceptions +from nesi.softbox.cli import base +import re + +class BaseCommandProcessor(base.CommandProcessor): + def do_exit(self, command, *args, context=None): + exc = exceptions.TerminalExitError() + exc.return_to = 'sysexit' + raise exc + + def create_spacers(self, positions, args): + spacers = [] + previous_pos = 0 + i = 0 + for position in positions: + spacer = position - (previous_pos + len(str(args[i]))) + spacers.append(spacer) + previous_pos = position + i += 1 + + return spacers \ No newline at end of file diff --git a/vendors/Zhone/main.py b/vendors/Zhone/main.py new file mode 100644 index 0000000..67dd517 --- /dev/null +++ b/vendors/Zhone/main.py @@ -0,0 +1,60 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi.softbox.cli import base +from vendors.Zhone.rootCommandProcessor import RootCommandProcessor +from nesi import exceptions + + +class PreLoginCommandProcessor(base.CommandProcessor): + + def on_unknown_command(self, command, *args, context=None): + subprocessor = self._create_subprocessor( + LoginCommandProcessor, 'login') + + context['username'] = context['raw_line'].replace('\r', '').replace('\n', '') + + try: + subprocessor.history_enabled = False + subprocessor.star_input = True + subprocessor.loop(context=context) + except exceptions.TerminalExitError as exc: + if exc.return_to is not None and exc.return_to != 'sysexit': + raise exc + else: + self.on_exit(context) + raise exc + + + +class LoginCommandProcessor(base.CommandProcessor): + + def on_unknown_command(self, command, *args, context=None): + username = context.pop('username') + password = command + + for creds in self._model.credentials: + if creds.username == username and creds.password == password: + break + + else: + text = self._render('password', context=context) + self._write(text) + raise exceptions.TerminalExitError() + + self.case_sensitive = False + + subprocessor = self._create_subprocessor( + RootCommandProcessor, 'login', 'base') + + context['path'] = '/' + context['component_path'] = '/' + + subprocessor.loop(context=context, return_to=RootCommandProcessor) + + self.on_exit(context) \ No newline at end of file diff --git a/vendors/Zhone/rootCommandProcessor.py b/vendors/Zhone/rootCommandProcessor.py new file mode 100644 index 0000000..5e1143d --- /dev/null +++ b/vendors/Zhone/rootCommandProcessor.py @@ -0,0 +1,33 @@ +# Software adapted by inexio . +# - Janis Groß +# - Philip Konrath +# - Alexander Dincher +# - Philipp-Noah Groß +# +# License: https://github.com/inexio/NESi/LICENSE.rst + +from nesi import exceptions +from vendors.Zhone.baseCommandProcessor import BaseCommandProcessor + +class RootCommandProcessor(BaseCommandProcessor): + + def on_unknown_command(self, command, *args, context=None): + raise exceptions.CommandSyntaxError(command=command) + + def get_property(self, command, *args, context=None): + raise exceptions.CommandExecutionError(command=command, template='invalid_property', + template_scopes=('login', 'base', 'execution_errors')) + + def do_dslstat(self, command, *args, context=None): + + if self._validate(args, *()): + self._write(self._render('dslstatEmptyArg', 'login', 'base', context=context)) + elif self._validate(args, "1/1/1/0/vdsl"): + + port = self._model.get_port('name', '1/1/1/0') + + context['port'] = port + + self._write(self._render('dslstatTemplate', 'login', 'base', context=context)) + else: + self._write(self._render('dslstatInvalidArg', 'login', 'base', context=context)) \ No newline at end of file From 28c02ac43600eea7bf70ae00c6d53d9f9b47de25 Mon Sep 17 00:00:00 2001 From: unkn0wn-user Date: Fri, 15 Jan 2021 10:19:38 +0100 Subject: [PATCH 2/3] Further implementation of dslstat command --- bootup/conf/bootstraps/create-zhone.sh | 33 +++++++++-- nesi/softbox/cli/base.py | 9 ++- .../Zhone/login/base/dslstatCyclePrompt.j2 | 2 + templates/Zhone/login/base/dslstatEmptyArg.j2 | 2 +- .../Zhone/login/base/dslstatInvalidArg.j2 | 3 +- templates/Zhone/login/base/dslstatTemplate.j2 | 16 +----- templates/Zhone/login/base/on_enter.j2 | 2 - vendors/Zhone/baseCommandProcessor.py | 21 +++++++ vendors/Zhone/main.py | 2 +- vendors/Zhone/rootCommandProcessor.py | 56 +++++++++++++++++-- 10 files changed, 113 insertions(+), 33 deletions(-) create mode 100644 templates/Zhone/login/base/dslstatCyclePrompt.j2 diff --git a/bootup/conf/bootstraps/create-zhone.sh b/bootup/conf/bootstraps/create-zhone.sh index 5532916..d2f06c3 100644 --- a/bootup/conf/bootstraps/create-zhone.sh +++ b/bootup/conf/bootstraps/create-zhone.sh @@ -36,10 +36,18 @@ req='{ box_id=$(create_resource "$req" $ENDPOINT/boxen) || exit 1 -# Sessionmanager credentials +# Admin user +req='{ + "name": "Admin" +}' + +admin_id=$(create_resource "$req" $ENDPOINT/boxen/$box_id/users) + +# Admin credentials req='{ "username": "admin", - "password": "secret" + "password": "secret", + "user_id": '$admin_id' }' admin_credential_id=$(create_resource "$req" $ENDPOINT/boxen/$box_id/credentials) @@ -57,7 +65,6 @@ subrack_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/subracks) req='{ "subrack_id": '$subrack_1', - "name": "1/1", "product": "vdsl", "description": "Karte von Juan" }' @@ -68,8 +75,7 @@ card_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/cards) req='{ "card_id": '$card_1', - "name": "1/1/1/0", - "description": "Port von Juan", + "description": "Network Port 1", "admin_state": "1", "operational_state": "1", "upLineRate": 5555, @@ -78,4 +84,19 @@ req='{ "maxDownLineRate": 2222 }' -port_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) \ No newline at end of file +port_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) + +# create a Port + +req='{ + "card_id": '$card_1', + "description": "Network Port 2", + "admin_state": "0", + "operational_state": "0", + "upLineRate": 5555, + "downLineRate": 4444, + "maxUpLineRate": 3333, + "maxDownLineRate": 2222 +}' + +port_2=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) \ No newline at end of file diff --git a/nesi/softbox/cli/base.py b/nesi/softbox/cli/base.py index 1632d66..637e27b 100644 --- a/nesi/softbox/cli/base.py +++ b/nesi/softbox/cli/base.py @@ -160,11 +160,13 @@ def get(self): def updateline(self, line): self._write('\r') # reset cursor to start of line - self._write('\033[' + str(self.prompt_end_pos + 1) + 'C') # move cursor to end of prompt + if self.prompt_end_pos != 0: + self._write('\033[' + str(self.prompt_end_pos + 1) + 'C') # move cursor to end of prompt self._write('\033[K') # clear rest of line self._write(line) # insert new line contents self._write('\r') # reset cursor to start of line - self._write('\033[' + str(self.cursor_pos) + 'C') # move cursor to correct position + if self.cursor_pos != 0: + self._write('\033[' + str(self.cursor_pos) + 'C') # move cursor to correct position def getline(self, tmp_boundary=None): char = None @@ -348,9 +350,6 @@ def loop(self, context=None, return_to=None, command=None): self.line_buffer = line.split('\r\n') continue context['raw_line'] = line - - if self.daemon: - self._write(line) # write line to stdout if box is in daemon mode else: line = command command = None diff --git a/templates/Zhone/login/base/dslstatCyclePrompt.j2 b/templates/Zhone/login/base/dslstatCyclePrompt.j2 new file mode 100644 index 0000000..d353857 --- /dev/null +++ b/templates/Zhone/login/base/dslstatCyclePrompt.j2 @@ -0,0 +1,2 @@ + for next page, for next line, A for all, Q to quit + diff --git a/templates/Zhone/login/base/dslstatEmptyArg.j2 b/templates/Zhone/login/base/dslstatEmptyArg.j2 index 46fb563..63a504a 100644 --- a/templates/Zhone/login/base/dslstatEmptyArg.j2 +++ b/templates/Zhone/login/base/dslstatEmptyArg.j2 @@ -1,2 +1,2 @@ -Not enough arguments. Please specify the name of the port. +Usage: dslstat <[ifIndex] | [name/type] | [shelf/slot/port/subport/type]> <-v> diff --git a/templates/Zhone/login/base/dslstatInvalidArg.j2 b/templates/Zhone/login/base/dslstatInvalidArg.j2 index eb5db2f..06d92e6 100644 --- a/templates/Zhone/login/base/dslstatInvalidArg.j2 +++ b/templates/Zhone/login/base/dslstatInvalidArg.j2 @@ -1,2 +1,3 @@ -The argument is invalid. +Unknown interface: {{ context.identifier }} +InfoIfTranslateGetFromString failed diff --git a/templates/Zhone/login/base/dslstatTemplate.j2 b/templates/Zhone/login/base/dslstatTemplate.j2 index fda93dc..14560a7 100644 --- a/templates/Zhone/login/base/dslstatTemplate.j2 +++ b/templates/Zhone/login/base/dslstatTemplate.j2 @@ -1,7 +1,7 @@ General Stats: ------------- -AdminStatus..................................UP -LineStatus...................................HANDSHAKE +AdminStatus..................................{{ context.port.admin_state }} +LineStatus...................................{{ context.port.operational_state }} DslUpLineRate (bitsPerSec)...................{{ context.port.upLineRate }} DslDownLineRate (bitsPerSec).................{{ context.port.downLineRate }} DslMaxAttainableUpLineRate (bitsPerSec)......{{ context.port.maxUpLineRate }} @@ -15,10 +15,6 @@ Out Pkts/Cells/Frags.........................0 Out Discards.................................0 Out Errors...................................0 -DSL Physical Stats: ------------------- -Out Errors...................................0 - DSL Physical Stats: ------------------ DslLineSnrMgn (tenths dB)....................0 @@ -39,11 +35,6 @@ Loss of Link Seconds.........................32170614 Severely Errored Seconds.....................32170614 Unavailable Seconds..........................32170614 -far-end statstics: -Loss of Link Seconds.........................32170614 -Severely Errored Seconds.....................32170614 -Unavailable Seconds..........................32170614 - far-end statstics: ----------------- Loss of Frame Seconds........................0 @@ -62,5 +53,4 @@ Vtuc UnCorrectable Retransmitted codewords...0 Vtur PhyRActive..............................FALSE Vtur Retransmitted codewords.................0 Vtur Corrected Retransmitted codewords.......0 -Vtur UnCorrectable Retransmitted codewords...0 - +Vtur UnCorrectable Retransmitted codewords...0 \ No newline at end of file diff --git a/templates/Zhone/login/base/on_enter.j2 b/templates/Zhone/login/base/on_enter.j2 index e607b9b..e69de29 100644 --- a/templates/Zhone/login/base/on_enter.j2 +++ b/templates/Zhone/login/base/on_enter.j2 @@ -1,2 +0,0 @@ -You logged in successfully. - diff --git a/vendors/Zhone/baseCommandProcessor.py b/vendors/Zhone/baseCommandProcessor.py index d80fd90..2b47956 100644 --- a/vendors/Zhone/baseCommandProcessor.py +++ b/vendors/Zhone/baseCommandProcessor.py @@ -16,6 +16,27 @@ def do_exit(self, command, *args, context=None): exc.return_to = 'sysexit' raise exc + def map_states(self, object, type): + if object.admin_state == '0': + if type == 'port': + object.admin_state = 'DOWN' + elif object.admin_state == '1': + if type == 'port': + object.admin_state = 'UP' + elif object.admin_state == '2': + if type == 'port': + object.admin_state = 'ERR' + + if object.operational_state == '0': + if type == 'port': + object.operational_state = 'DOWN' + elif object.operational_state == '1': + if type == 'port': + object.operational_state = 'DATA' + elif object.operational_state == '2': + if type == 'port': + object.operational_state = 'HANDSHAKE' + def create_spacers(self, positions, args): spacers = [] previous_pos = 0 diff --git a/vendors/Zhone/main.py b/vendors/Zhone/main.py index 67dd517..5be48e3 100644 --- a/vendors/Zhone/main.py +++ b/vendors/Zhone/main.py @@ -21,7 +21,7 @@ def on_unknown_command(self, command, *args, context=None): try: subprocessor.history_enabled = False - subprocessor.star_input = True + subprocessor.hide_input = True subprocessor.loop(context=context) except exceptions.TerminalExitError as exc: if exc.return_to is not None and exc.return_to != 'sysexit': diff --git a/vendors/Zhone/rootCommandProcessor.py b/vendors/Zhone/rootCommandProcessor.py index 5e1143d..c1fcfbc 100644 --- a/vendors/Zhone/rootCommandProcessor.py +++ b/vendors/Zhone/rootCommandProcessor.py @@ -19,15 +19,63 @@ def get_property(self, command, *args, context=None): template_scopes=('login', 'base', 'execution_errors')) def do_dslstat(self, command, *args, context=None): - if self._validate(args, *()): self._write(self._render('dslstatEmptyArg', 'login', 'base', context=context)) - elif self._validate(args, "1/1/1/0/vdsl"): + elif self._validate(args, str): + identifier, = self._dissect(args, str) + identifier_components = identifier.split('/') + if len(identifier_components) != 5 or identifier_components[3] != '0' or identifier_components[4] != 'vdsl': + context['identifier'] = identifier + self._write(self._render('dslstatInvalidArg', 'login', 'base', context=context)) + return + port = self._model.get_port('name', "/".join(identifier_components[:3])) - port = self._model.get_port('name', '1/1/1/0') + self.map_states(port, 'port') context['port'] = port - self._write(self._render('dslstatTemplate', 'login', 'base', context=context)) + if self.daemon and self._model.network_protocol == 'ssh': + output = self._render('dslstatTemplate', 'login', 'base', context=context).split("\n") + pointer = 0 + buff_size = 19 + prompt_end = self.prompt_end_pos + while True: + self.cursor_pos = 0 + self._write("\n".join(output[pointer:pointer + buff_size])) + self._write("\n") + pointer += buff_size + + if pointer >= len(output): + break + + option_string = ' for next page, for next line, A for all, Q to quit' + self.cursor_pos = len(option_string) + 1 + self.prompt_end_pos = 0 + self.updateline(option_string) + + character = None + + while character not in ('\r', 'a', 'q', ' '): + _, character = self.get() + + self.cursor_pos = 0 + self.updateline('') + + if character == '\r': + buff_size = 1 + continue + elif character == 'a': + buff_size = len(output) - pointer + continue + elif character == 'q': + break + elif character == ' ': + buff_size = 19 + continue + self.cursor_pos = 0 + self.prompt_end_pos = prompt_end + else: + output = self._render('dslstatTemplate', 'login', 'base', context=context) + "\n" + self._write(output) else: self._write(self._render('dslstatInvalidArg', 'login', 'base', context=context)) \ No newline at end of file From b70eafb765c5eecc5cba12d51ad3bdb24df9d60d Mon Sep 17 00:00:00 2001 From: unkn0wn-user Date: Fri, 15 Jan 2021 11:17:11 +0100 Subject: [PATCH 3/3] Fixed wrong fields in zhone / relocated up/downstream fields into base port --- bootup/conf/bootstraps/create-zhone.sh | 16 +++++++------- .../alcatel/alcatel_resources/alcatel_port.py | 4 ---- .../api/schemas/alcatel_port_schemas.py | 3 +-- .../huawei/api/schemas/huawei_port_schemas.py | 3 +-- nesi/huawei/huawei_resources/huawei_port.py | 4 ---- .../keymile/keymile_resources/keymile_port.py | 2 -- nesi/softbox/api/models/port_models.py | 6 ------ nesi/softbox/api/schemas/port_schemas.py | 2 +- nesi/softbox/base_resources/port.py | 4 ++++ nesi/zhone/api/schemas/zhone_port_schemas.py | 2 +- nesi/zhone/zhone_resources/zhone_port.py | 6 ------ templates/Zhone/login/base/dslstatTemplate.j2 | 8 +++---- .../integration_tests/zhone/dslstat.txt | 4 ++++ test_cases/unit_tests/zhone/test_zhone.py | 21 ++++++++----------- 14 files changed, 33 insertions(+), 52 deletions(-) create mode 100644 test_cases/integration_tests/zhone/dslstat.txt diff --git a/bootup/conf/bootstraps/create-zhone.sh b/bootup/conf/bootstraps/create-zhone.sh index d2f06c3..a17859b 100644 --- a/bootup/conf/bootstraps/create-zhone.sh +++ b/bootup/conf/bootstraps/create-zhone.sh @@ -78,10 +78,10 @@ req='{ "description": "Network Port 1", "admin_state": "1", "operational_state": "1", - "upLineRate": 5555, - "downLineRate": 4444, - "maxUpLineRate": 3333, - "maxDownLineRate": 2222 + "upstream": 4023, + "downstream": 13232, + "upstream_max": 8000, + "downstream_max": 16000 }' port_1=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) @@ -93,10 +93,10 @@ req='{ "description": "Network Port 2", "admin_state": "0", "operational_state": "0", - "upLineRate": 5555, - "downLineRate": 4444, - "maxUpLineRate": 3333, - "maxDownLineRate": 2222 + "upstream": 4023, + "downstream": 13232, + "upstream_max": 8000, + "downstream_max": 16000 }' port_2=$(create_resource "$req" $ENDPOINT/boxen/$box_id/ports) \ No newline at end of file diff --git a/nesi/alcatel/alcatel_resources/alcatel_port.py b/nesi/alcatel/alcatel_resources/alcatel_port.py index 8864d12..c322830 100644 --- a/nesi/alcatel/alcatel_resources/alcatel_port.py +++ b/nesi/alcatel/alcatel_resources/alcatel_port.py @@ -22,10 +22,6 @@ class AlcatelPort(Port): mode = base.Field('mode') shutdown = base.Field('shutdown') speed = base.Field('speed') - upstream = base.Field('upstream') - downstream = base.Field('downstream') - upstream_max = base.Field('upstream_max') - downstream_max = base.Field('downstream_max') noise_margin_up = base.Field('noise_margin_up') noise_margin_down = base.Field('noise_margin_down') tgt_noise_margin_up = base.Field('tgt_noise_margin_up') diff --git a/nesi/alcatel/api/schemas/alcatel_port_schemas.py b/nesi/alcatel/api/schemas/alcatel_port_schemas.py index 36571a3..f3680e8 100644 --- a/nesi/alcatel/api/schemas/alcatel_port_schemas.py +++ b/nesi/alcatel/api/schemas/alcatel_port_schemas.py @@ -16,8 +16,7 @@ class AlcatelPortSchema(PortSchema): class Meta: model = Port - fields = PortSchema.Meta.fields + ('shutdown', 'speed', 'upstream', 'downstream', 'upstream_max', - 'downstream_max', 'noise_margin_up', 'noise_margin_down', + fields = PortSchema.Meta.fields + ('shutdown', 'speed', 'noise_margin_up', 'noise_margin_down', 'tgt_noise_margin_up', 'tgt_noise_margin_down', 'attenuation_up', 'attenuation_down', 'attained_upstream', 'attained_downstream', 'threshold_upstream', 'threshold_downstream', 'max_delay_upstream', diff --git a/nesi/huawei/api/schemas/huawei_port_schemas.py b/nesi/huawei/api/schemas/huawei_port_schemas.py index c56dbb4..f2ee5f8 100644 --- a/nesi/huawei/api/schemas/huawei_port_schemas.py +++ b/nesi/huawei/api/schemas/huawei_port_schemas.py @@ -16,8 +16,7 @@ class HuaweiPortSchema(PortSchema): class Meta: model = Port - fields = PortSchema.Meta.fields + ('upstream', 'downstream', 'upstream_max', 'downstream_max', - 'line_template', 'loopback', 'sos_profile', 'sos_profile_num', + fields = PortSchema.Meta.fields + ('line_template', 'loopback', 'sos_profile', 'sos_profile_num', 'alarm_template', 'dynamic_profile_index', 'dynamic_profile_name', 'hardware', 'last_up_time', 'last_down_time', 'show_time', 'nte_power_status', 'current_operational_mode', 'cpes', 'description', diff --git a/nesi/huawei/huawei_resources/huawei_port.py b/nesi/huawei/huawei_resources/huawei_port.py index 8f0400d..61bee77 100644 --- a/nesi/huawei/huawei_resources/huawei_port.py +++ b/nesi/huawei/huawei_resources/huawei_port.py @@ -21,10 +21,6 @@ class HuaweiPort(Port): cpes = base.Field('cpes') description = base.Field('description') - upstream = base.Field('upstream') - downstream = base.Field('downstream') - upstream_max = base.Field('upstream_max') - downstream_max = base.Field('downstream_max') loopback = base.Field('loopback') line_template = base.Field('line_template') alarm_template = base.Field('alarm_template') diff --git a/nesi/keymile/keymile_resources/keymile_port.py b/nesi/keymile/keymile_resources/keymile_port.py index c976869..81a248d 100644 --- a/nesi/keymile/keymile_resources/keymile_port.py +++ b/nesi/keymile/keymile_resources/keymile_port.py @@ -36,8 +36,6 @@ class KeyMilePort(Port): profile4_enable = base.Field('profile4_enable') profile4_name = base.Field('profile4_name') profile_mode = base.Field('profile_mode') - upstream = base.Field('upstream') - downstream = base.Field('downstream') def set_profile(self, name): self.update(profile1_name=name) diff --git a/nesi/softbox/api/models/port_models.py b/nesi/softbox/api/models/port_models.py index da78916..6ed09a0 100644 --- a/nesi/softbox/api/models/port_models.py +++ b/nesi/softbox/api/models/port_models.py @@ -331,9 +331,3 @@ class Port(db.Model): profile4_enable = db.Column(db.Boolean(), default=False) profile4_name = db.Column(db.String(), default='') profile_mode = db.Column(db.Enum('Priority', 'ElectricalLoopLength'), default=None) - - #Zhone - upLineRate = db.Column(db.Integer(), default=0) - downLineRate = db.Column(db.Integer(), default=0) - maxUpLineRate = db.Column(db.Integer(), default=0) - maxDownLineRate = db.Column(db.Integer(), default=0) diff --git a/nesi/softbox/api/schemas/port_schemas.py b/nesi/softbox/api/schemas/port_schemas.py index 83679f3..bf580fc 100644 --- a/nesi/softbox/api/schemas/port_schemas.py +++ b/nesi/softbox/api/schemas/port_schemas.py @@ -22,7 +22,7 @@ class PortSchema(ma.ModelSchema): class Meta: model = Port fields = ('id', 'box_id', 'box', 'card_id', 'cpes', 'onts', 'channels', 'loopback', 'name', 'interfaces', - 'description', 'admin_state', 'operational_state', '_links') + 'description', 'admin_state', 'operational_state', 'upstream', 'upstream_max', 'downstream', 'downstream_max', '_links') cpes = ma.Nested(CpesSchema.CpeSchema, many=True) diff --git a/nesi/softbox/base_resources/port.py b/nesi/softbox/base_resources/port.py index 5b51433..c02a0df 100644 --- a/nesi/softbox/base_resources/port.py +++ b/nesi/softbox/base_resources/port.py @@ -27,6 +27,10 @@ class Port(base.Resource): description = base.Field('description') admin_state = base.Field('admin_state') operational_state = base.Field('operational_state') + upstream = base.Field('upstream') + downstream = base.Field('downstream') + upstream_max = base.Field('upstream_max') + downstream_max = base.Field('downstream_max') def admin_up(self): """Set the admin port state to up""" diff --git a/nesi/zhone/api/schemas/zhone_port_schemas.py b/nesi/zhone/api/schemas/zhone_port_schemas.py index 56f088c..05838e8 100644 --- a/nesi/zhone/api/schemas/zhone_port_schemas.py +++ b/nesi/zhone/api/schemas/zhone_port_schemas.py @@ -11,5 +11,5 @@ class ZhonePortSchema(PortSchema): class Meta: model = Port - fields = PortSchema.Meta.fields + ('upLineRate', 'downLineRate', 'maxUpLineRate', 'maxDownLineRate') + fields = PortSchema.Meta.fields diff --git a/nesi/zhone/zhone_resources/zhone_port.py b/nesi/zhone/zhone_resources/zhone_port.py index 51c2656..41fc631 100644 --- a/nesi/zhone/zhone_resources/zhone_port.py +++ b/nesi/zhone/zhone_resources/zhone_port.py @@ -18,15 +18,9 @@ class ZhonePort(Port): - upLineRate = base.Field("upLineRate") - downLineRate = base.Field("downLineRate") - maxUpLineRate = base.Field("maxUpLineRate") - maxDownLineRate = base.Field("maxDownLineRate") - """Represent physical port resource.""" - class ZhonePortCollection(PortCollection): """Represent a collection of ports.""" diff --git a/templates/Zhone/login/base/dslstatTemplate.j2 b/templates/Zhone/login/base/dslstatTemplate.j2 index 14560a7..9df55fd 100644 --- a/templates/Zhone/login/base/dslstatTemplate.j2 +++ b/templates/Zhone/login/base/dslstatTemplate.j2 @@ -2,10 +2,10 @@ General Stats: ------------- AdminStatus..................................{{ context.port.admin_state }} LineStatus...................................{{ context.port.operational_state }} -DslUpLineRate (bitsPerSec)...................{{ context.port.upLineRate }} -DslDownLineRate (bitsPerSec).................{{ context.port.downLineRate }} -DslMaxAttainableUpLineRate (bitsPerSec)......{{ context.port.maxUpLineRate }} -DslMaxAttainableDownLineRate (bitsPerSec)....{{ context.port.maxDownLineRate }} +DslUpLineRate (bitsPerSec)...................{{ context.port.upstream }} +DslDownLineRate (bitsPerSec).................{{ context.port.downstream }} +DslMaxAttainableUpLineRate (bitsPerSec)......{{ context.port.upstream_max }} +DslMaxAttainableDownLineRate (bitsPerSec)....{{ context.port.downstream_max }} In Octets....................................0 In Pkts/Cells/Frags..........................0 In Discards..................................0 diff --git a/test_cases/integration_tests/zhone/dslstat.txt b/test_cases/integration_tests/zhone/dslstat.txt new file mode 100644 index 0000000..393132c --- /dev/null +++ b/test_cases/integration_tests/zhone/dslstat.txt @@ -0,0 +1,4 @@ +admin +secret +dslstat 1/1/1/0/vdsl +exit \ No newline at end of file diff --git a/test_cases/unit_tests/zhone/test_zhone.py b/test_cases/unit_tests/zhone/test_zhone.py index ea9b941..9b11fa3 100644 --- a/test_cases/unit_tests/zhone/test_zhone.py +++ b/test_cases/unit_tests/zhone/test_zhone.py @@ -16,18 +16,15 @@ class TestZhone(TestCore): def test_portup_portdown(self): - port = self.model.get_port("name", '1/1/1/1') - assert(self.model.get_port("name", '1/1/1/1').admin_state == 'down') - port.admin_up() - assert(self.model.get_port("name", '1/1/1/1').admin_state == 'up') + port = self.model.get_port("name", '1/1/1') + assert(self.model.get_port("name", '1/1/1').admin_state == '1') port.admin_down() - assert(self.model.get_port("name", '1/1/1/1').admin_state == 'down') - - def test_ontportup_portdown(self): - port = self.model.get_ont_port("name", '1/1/4/1/1/1/1') - assert(self.model.get_ont_port("name", '1/1/4/1/1/1/1').admin_state == 'down') + assert(self.model.get_port("name", '1/1/1').admin_state == '0') port.admin_up() - assert(self.model.get_ont_port("name", '1/1/4/1/1/1/1').admin_state == 'up') - port.admin_down() - assert(self.model.get_ont_port("name", '1/1/4/1/1/1/1').admin_state == 'down') + assert(self.model.get_port("name", '1/1/1').admin_state == '1') + assert (self.model.get_port("name", '1/1/1').operational_state == '1') + port.down() + assert (self.model.get_port("name", '1/1/1').operational_state == '0') + port.up() + assert (self.model.get_port("name", '1/1/1').operational_state == '1')