Skip to content
Snippets Groups Projects
Commit b21ad589 authored by Karel van Klink's avatar Karel van Klink :smiley_cat: Committed by Neda Moeini
Browse files

udpate documentation, resolve linter warnings

parent d2ed1e7e
No related branches found
No related tags found
1 merge request!115Feature/update docs
Showing
with 70 additions and 68 deletions
# GÉANT Service Orchestrator
The GÉANT interpretation of [`orchestrator-core`](https://github.com/workfloworchestrator/orchestrator-core).
The GÉANT interpretation of [``orchestrator-core``](https://github.com/workfloworchestrator/orchestrator-core).
## Documentation
You can build the documentation locally using [build-docs.sh](build-docs.sh).
#!/bin/sh
set -o errexit
set -o nounset
export OSS_PARAMS_FILENAME=../gso/oss-params-example.json
pip install sphinx_rtd_theme sphinxcontrib-jquery
cd docs || exit 1
cd docs
sphinx-build source build
......@@ -14,6 +14,9 @@ Glossary of terms
Classless Inter-Domain Routing. A method for denoting IP ranges in the form of ``9.9.0.0/16`` or
``fe80:1234:abcd::/48``.
CLI
Command Line Interface.
CNAME
A type of DNS record that is used as an alias from one hostname to another
......@@ -26,10 +29,13 @@ Glossary of terms
GSO
GÉANT Service Orchestrator
IAS
IAS
IPAM
IP Address Management
IS-IS
ISIS
Intermediate System to Intermediate System: a routing protocol described in
`RFC 7142 <https://datatracker.ietf.org/doc/html/rfc7142>`_.
......@@ -43,7 +49,7 @@ Glossary of terms
Lightweight Service Orchestrator
NET
Network Entity Title: used for :term:`IS-IS` routing.
Network Entity Title: used for :term:`ISIS` routing.
OSS
Operational Support Systems
......
......@@ -13,13 +13,3 @@ Subpackages
product_blocks/index
product_types/index
Submodules
----------
``gso.products.shared`` module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automodule:: gso.products.shared
:members:
:show-inheritance:
......@@ -17,4 +17,3 @@ Submodules
modify_isis_metric
modify_trunk_interface
terminate_iptrunk
utils
GÉANT Automation Platform
[GSO|gso]
Vereniging
[[T|t]ERMINATE|terminate]
[[T|t]erminate|TERMINATE]
WFO
Ansible
[Dd]eprovision
......@@ -12,3 +12,4 @@ Dark_fiber
[I|i]ptrunk
[A|a]llocate
PHASE 1
[Mm]odify
......@@ -71,8 +71,7 @@ class SiteImportModel(BaseModel):
def site_name_must_be_valid(cls, site_name: str) -> str:
"""Validate the site name.
The site name must consist of three uppercase letters (A-Z) followed
by an optional single digit (0-9).
The site name must consist of three uppercase letters, optionally followed by a single digit.
"""
validate_site_fields_is_unique("site_name", site_name)
validate_site_name(site_name)
......
......@@ -149,7 +149,7 @@ class IptrunkBlock(IptrunkBlockProvisioning, lifecycle=[SubscriptionLifecycle.AC
iptrunk_speed: PhyPortCapacity
#: The minimum amount of links the trunk should consist of.
iptrunk_minimum_links: int
#: The :term:`IS-IS` metric of this link
#: The :term:`ISIS` metric of this link
iptrunk_isis_metric: int
#: The IPv4 network used for this trunk.
iptrunk_ipv4_network: ipaddress.IPv4Network
......
......@@ -96,13 +96,13 @@ class RouterBlock(RouterBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTI
router_lo_ipv4_address: ipaddress.IPv4Address
#: The IPv6 loopback address of the router.
router_lo_ipv6_address: ipaddress.IPv6Address
#: The :term:`ISO` :term:`NET` of the router, used for :term:`IS-IS` support.
#: The :term:`ISO` :term:`NET` of the router, used for :term:`ISIS` support.
router_lo_iso_address: str
#: The SI IPv4 network of the router.
router_si_ipv4_network: ipaddress.IPv4Network | None
#: The IAS LT IPv4 network of the router.
#: The :term:`IAS` LT IPv4 network of the router.
router_ias_lt_ipv4_network: ipaddress.IPv4Network | None
#: The IAS LT IPv6 network of the router.
#: The :term:`IAS` LT IPv6 network of the router.
router_ias_lt_ipv6_network: ipaddress.IPv6Network | None
#: The vendor of the router, can be any of the values defined in :class:`RouterVendor`.
router_vendor: RouterVendor
......@@ -110,5 +110,5 @@ class RouterBlock(RouterBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTI
router_role: RouterRole
#: The :class:`Site` that this router resides in. Both physically and computationally.
router_site: SiteBlock
#: The router is going to have an LT interface between inet0 and IAS
#: The router is going to have an LT interface between inet0 and :term:`IAS`.
router_is_ias_connected: bool
......@@ -119,5 +119,5 @@ class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE])
site_tier: SiteTier
#: The address of the terminal server that this router is connected to. The terminal server provides out of band
#: access. This is required in case a link goes down, or when a router is initially added to the network and it
#: does not have any IP trunks connected to it yet.
#: does not have any IP trunks connected to it.
site_ts_address: str | None = None
"""Definition of the decorator that allows for scheduling tasks in :term:`GSO` that are to run periodically."""
"""Definition of the decorator that schedules tasks in :term:`GSO` that are to run periodically."""
import inspect
from collections.abc import Callable
......@@ -21,11 +21,11 @@ def scheduler(
Examples
--------
- `minute='*/15'`: Run every 15 minutes.
- `hour='*/3'`: Run every 3 hours.
- `day_of_week='mon-fri'`: Run on weekdays only.
- `day_of_month='1-7,15-21'`: Run on the first and third weeks of the month.
- `month_of_year='*/3'`: Run on the first month of each quarter.
- ``minute='*/15'``: Run every 15 minutes.
- ``hour='*/3'``: Run every 3 hours.
- ``day_of_week='mon-fri'``: Run on weekdays only.
- ``day_of_month='1-7,15-21'``: Run on the first and third weeks of the month.
- ``month_of_year='*/3'``: Run on the first month of each quarter.
All time units can be specified with lists of numbers or crontab pattern strings for advanced scheduling.
All specified time parts (minute, hour, day, etc.) must align for a task to run.
......
"""A module that returns the customers available in :term:`GSO`.
For the time being, it's hardcoded to only contain GÉANT as a customer, since this is needed for PHASE 1 deployment.
For the time being, it's hardcoded to only contain GÉANT as a customer, since this is needed for the deployment of phase
1.
"""
from typing import Any
......
"""The Infoblox service that allows :term:`GSO` to allocate :term:`IPAM` resources that are used in products."""
"""The Infoblox service that allocates :term:`IPAM` resources used in :term:`GSO` products."""
import ipaddress
from logging import getLogger
......@@ -53,7 +53,7 @@ def _allocate_network(
:param conn: An active Infoblox connection.
:type conn: :class:`infoblox_client.connector.Connector`
:param dns_view: The Infoblox `dns_view` in which the network should be allocated.
:param dns_view: The Infoblox ``dns_view`` in which the network should be allocated.
:type dns_view: str
:param netmask: The netmask of the desired network. Can be up to 32 for v4 networks, and 128 for v6 networks.
:type netmask: int
......@@ -178,7 +178,7 @@ def allocate_host(
:param cname_aliases: A list of any :term:`CNAME` aliases that should be associated with this host. Most often this
will be a single loopback address.
:type cname_aliases: list[str]
:param comment: A comment that is added to the host record in Infoblox, should be the `subscription_id` of the new
:param comment: A comment that is added to the host record in Infoblox, should be the ``subscription_id`` of the new
:class:`Router` subscription.
:type comment: str
"""
......
......@@ -213,10 +213,10 @@ class NetboxClient:
"""
iface = self.get_interface_by_name_and_device(iface_name, device_name)
# Get LAG
# Get :term:`LAG`
lag = self.get_interface_by_name_and_device(lag_name, device_name)
# Assign interface to LAG, ensuring it doesn't already belong to a LAG
# Assign interface to :term:`LAG`, ensuring it does not already belong to a :term:`LAG`.
if iface.lag:
msg = f"The interface: {iface_name} on device: {device_name} already belongs to a LAG: {iface.lag.name}."
raise WorkflowStateError(
......@@ -275,7 +275,7 @@ class NetboxClient:
return interface
def detach_interfaces_from_lag(self, device_name: str, lag_name: str) -> None:
"""Detach all interfaces from a LAG."""
"""Detach all interfaces from a :term:`LAG`."""
device = self.get_device_by_name(device_name)
lag = self.netbox.dcim.interfaces.get(device_id=device.id, name=lag_name)
for interface in self.netbox.dcim.interfaces.filter(
......@@ -288,11 +288,11 @@ class NetboxClient:
interface.save()
def get_available_lags(self, router_id: UUID) -> list[str]:
"""Return all available :term:`LAG`s not assigned to a device."""
"""Return all available :term:`LAG` not assigned to a device."""
router_name = Router.from_subscription(router_id).router.router_fqdn
device = self.get_device_by_name(router_name)
# Get the existing LAG interfaces for the device
# Get the existing :term:`LAG` interfaces for the device
lag_interface_names = [
interface["name"] for interface in self.netbox.dcim.interfaces.filter(device=device.name, type="lag")
]
......
......@@ -101,7 +101,7 @@ def provision_router(
:type callback_route: str
:param tt_number: Trouble ticket number related to the operation.
:type tt_number: str
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``.
:type dry_run: bool
:rtype: None
"""
......@@ -137,11 +137,11 @@ def provision_ip_trunk(
:type tt_number: str
:param config_object: The type of object that's deployed.
:type config_object: str
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``.
:type dry_run: bool
:rtype: None
:param removed_ae_members: A list of interfaces that are removed from the :term:`LAG`, defaults to `None`.
it's only used when we removed some interfaces from the LAG in modify_ip_trunk.
:param removed_ae_members: A list of interfaces that are removed from the :term:`LAG`, defaults to ``None``.
only used when removing interfaces from the :term:`LAG` in ``modify_ip_trunk``.
"""
parameters = {
"subscription": json.loads(json_dumps(subscription)),
......@@ -204,7 +204,7 @@ def deprovision_ip_trunk(
:type callback_route: str
:param tt_number: Trouble ticket number related to the operation.
:type tt_number: str
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``.
:type dry_run: bool
:rtype: None
"""
......@@ -237,14 +237,14 @@ def migrate_ip_trunk(
:param subscription: The subscription object that's to be migrated.
:type subscription: :class:`Iptrunk`
:param new_node: The new node that is being migrated to
:param new_node: The new node that is being migrated to.
:type new_node: :class:`Router`
:param new_lag_interface: The name of the new aggregated Ethernet interface
:param new_lag_interface: The name of the new aggregated Ethernet interface.
:type new_lag_interface: str
:param new_lag_member_interfaces: The new list of interfaces that are part of the :term:`LAG`
:param new_lag_member_interfaces: The new list of interfaces that are part of the :term:`LAG`.
:type new_lag_member_interfaces: list[str]
:param replace_index: The index of the side that is going to be replaced as part of the existing trunk,
can be `0` or `1`.
:param replace_index: The index of the side that is going to be replaced as part of the existing trunk, can be ``0``
or ``1``.
:type replace_index: int
:param process_id: The related process ID, used for callback.
:type process_id: UUIDstr
......@@ -252,11 +252,11 @@ def migrate_ip_trunk(
:type callback_route: str
:param tt_number: Trouble ticket number related to the operation.
:type tt_number: str
:param verb: The verb that is passed to the executed playbook
:param verb: The verb that is passed to the executed playbook.
:type verb: str
:param config_object: The object that is configured.
:type config_object: str
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to `True`.
:param dry_run: A boolean indicating whether this should be a dry run or not, defaults to ``True``.
:type dry_run: bool
:rtype: None
"""
......@@ -306,8 +306,8 @@ def pp_interaction(provisioning_step: Step) -> StepList:
"""Interact with the provisioning proxy :term:`LSO` using a callback step.
An asynchronous interaction with the provisioning proxy. This is an external system that executes Ansible playbooks
in order to provision service subscriptions. If the playbook fails, this step will also fail, allowing for the user
to retry provisioning from the UI.
to provision service subscriptions. If the playbook fails, this step will also fail, allowing for the user to retry
provisioning from the UI.
:param provisioning_step: A workflow step that performs an operation remotely using the provisioning proxy.
:type provisioning_step: :class:`Step`
......
"""A collection of methods that make interaction with coreDB more straight-forward.
This prevents someone from having to re-write database statements multiple times, that might turn out to be erroneous
This prevents someone from having to re-write database statements many times, that might turn out to be erroneous
or inconsistent when not careful.
"""
......@@ -103,7 +103,7 @@ def get_active_subscriptions_by_field_and_value(field_name: str, field_value: st
:param field_name: The name of the field to filter by.
:type field_name: str
:param field_value: The value of the field to match against.
:param field_value: The value of the field to match.
:type field_value: Any
:return: A list of active Subscription objects that match the criteria.
......
"""Utility module that contains helper methods, exceptions, etc."""
"""Utility module that has helper methods, exceptions, etc."""
......@@ -209,12 +209,12 @@ def validate_country_code(country_code: str) -> str:
def validate_site_name(site_name: str) -> str:
"""Validate the site name.
The site name must consist of three uppercase letters (A-Z) followed by an optional single digit (0-9).
The site name must consist of three uppercase letters, optionally followed by a single digit.
"""
pattern = re.compile(r"^[A-Z]{3}[0-9]?$")
if not pattern.match(site_name):
msg = (
"Enter a valid site name. It must consist of three uppercase letters (A-Z) followed by an optional single "
"Enter a valid site name. It must consist of three uppercase letters (A-Z), followed by an optional single "
f"digit (0-9). Received: {site_name}"
)
raise ValueError(msg)
......
......@@ -335,11 +335,11 @@ def check_ip_trunk_isis(
@step("NextBox integration")
def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State:
"""Create the LAG interfaces in NetBox and attach the lag interfaces to the physical interfaces."""
"""Create the :term:`LAG` interfaces in NetBox and attach the lag interfaces to the physical interfaces."""
nbclient = NetboxClient()
for trunk_side in subscription.iptrunk.iptrunk_sides:
if trunk_side.iptrunk_side_node.router_vendor == RouterVendor.NOKIA:
# Create LAG interfaces
# Create :term:`LAG` interfaces
lag_interface: Interfaces = nbclient.create_interface(
iface_name=trunk_side.iptrunk_side_ae_iface,
interface_type="lag",
......@@ -347,7 +347,7 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State:
description=str(subscription.subscription_id),
enabled=True,
)
# Attach physical interfaces to LAG
# Attach physical interfaces to :term:`LAG`
# Update interface description to subscription ID
# Reserve interfaces
for interface in trunk_side.iptrunk_side_ae_members:
......@@ -368,7 +368,7 @@ def reserve_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State:
@step("Allocate interfaces in Netbox")
def allocate_interfaces_in_netbox(subscription: IptrunkProvisioning) -> State:
"""Allocate the LAG interfaces in NetBox and attach the lag interfaces to the physical interfaces."""
"""Allocate the :term:`LAG` interfaces in NetBox and attach the lag interfaces to the physical interfaces."""
for trunk_side in subscription.iptrunk.iptrunk_sides:
if trunk_side.iptrunk_side_node.router_vendor == RouterVendor.NOKIA:
for interface in trunk_side.iptrunk_side_ae_members:
......
......@@ -43,7 +43,7 @@ logger = getLogger(__name__)
def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"""Gather input from the operator on the new router that the IP trunk should terminate on."""
"""Gather input from the operator on the new router that the IP trunk should connect to."""
subscription = Iptrunk.from_subscription(subscription_id)
form_title = (
f"Subscription {subscription.iptrunk.geant_s_sid} "
......@@ -498,7 +498,7 @@ def reserve_interfaces_in_netbox(
nbclient = NetboxClient()
if new_side.router_vendor == RouterVendor.NOKIA:
# Create LAG interfaces
# Create :term:`LAG` interfaces
lag_interface: Interfaces = nbclient.create_interface(
iface_name=new_lag_interface,
interface_type="lag",
......@@ -506,7 +506,7 @@ def reserve_interfaces_in_netbox(
description=str(subscription.subscription_id),
enabled=True,
)
# Attach physical interfaces to LAG
# Attach physical interfaces to :term:`LAG`
# Reserve interfaces
for interface in new_lag_member_interfaces:
nbclient.attach_interface_to_lag(
......@@ -545,7 +545,7 @@ def update_netbox(
iface["interface_name"],
)
# Delete LAG interfaces
# Delete :term:`LAG` interfaces
nbclient.delete_interface(
old_side_data["iptrunk_side_node"]["router_fqdn"],
old_side_data["iptrunk_side_ae_iface"],
......@@ -563,7 +563,7 @@ def migrate_iptrunk() -> StepList:
* Reserve new interfaces in Netbox
* Set the :term:`ISIS` metric of the current trunk to an arbitrarily high value to drain all traffic
* Disable - but don't delete - the old configuration on the routers, first as a dry run
* Disable - but do not delete - the old configuration on the routers, first as a dry run
* Deploy the new configuration on the routers, first as a dry run
* Wait for operator confirmation that the physical fiber has been moved before continuing
* Deploy a new :term:`ISIS` interface between routers A and C
......@@ -571,7 +571,7 @@ def migrate_iptrunk() -> StepList:
* Restore the old :term:`ISIS` metric on the new trunk
* Delete the old, disabled configuration on the routers, first as a dry run
* Reflect the changes made in :term:`IPAM`
* Update the subscription model in the database accordingly
* Update the subscription model in the database
* Update the reserved interfaces in Netbox
TODO: add interface checks
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment