Skip to content
Snippets Groups Projects
Commit 8e080399 authored by Karel van Klink's avatar Karel van Klink :smiley_cat: Committed by Mohammad Torkashvand
Browse files

Update docstrings to be added in mkdocs

parent 5cad4fb0
No related branches found
No related tags found
1 merge request!329Feature/update docstrings
Pipeline #90947 passed
This commit is part of merge request !329. Comments created here will be created in the context of that merge request.
Showing
with 172 additions and 149 deletions
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*[CFS]: Customer Facing Service *[CFS]: Customer Facing Service
*[CIDR]: Classless Inter-Domain Routing *[CIDR]: Classless Inter-Domain Routing
*[DCIM]: Datacenter Infrastructure Manager *[DCIM]: Datacenter Infrastructure Manager
*[DCN]: Datacenter Network
*[DHCP]: Dynamic Host Configuration Protocol *[DHCP]: Dynamic Host Configuration Protocol
*[DNS]: Domain Name System *[DNS]: Domain Name System
*[DTAP]: Development, Testing, Acceptance, and Production *[DTAP]: Development, Testing, Acceptance, and Production
......
...@@ -33,7 +33,7 @@ with Path.open(root / "docs" / "wf_redirects.yaml", "w") as redirect_file: ...@@ -33,7 +33,7 @@ with Path.open(root / "docs" / "wf_redirects.yaml", "w") as redirect_file:
{"gen-files": {"scripts": ["scripts/gen_ref_pages.py"]}}, {"gen-files": {"scripts": ["scripts/gen_ref_pages.py"]}},
{"redirects": {"redirect_maps": redirect_map}}, {"redirects": {"redirect_maps": redirect_map}},
{"literate-nav": {"nav_file": "SUMMARY.md"}}, {"literate-nav": {"nav_file": "SUMMARY.md"}},
"mkdocstrings", {"mkdocstrings": {"handlers": {"python": {"options": {"filters": [], "members_order": "source"}}}}},
] ]
} }
yaml.dump(file_content, redirect_file) yaml.dump(file_content, redirect_file)
# Components of GAP # Components of GAP
As stated before, GAP is a platform and not a monolithic piece of software. GAP interacts with different OSS/BSS As stated before, GAP is a platform and not a monolithic piece of software. GAP interacts with different OSS/BSS
systems already present in GÉANT and these are tightly integrated with the automation platform. systems already present in GÉANT and these are integrated with the automation platform.
From a high level point of view, GAP can be seen as the sum of the following parts: From a high level point of view, GAP can be seen as the sum of the following parts:
......
...@@ -57,16 +57,12 @@ configuration backups of routers, switches, and any other network devices that a ...@@ -57,16 +57,12 @@ configuration backups of routers, switches, and any other network devices that a
More detailed information about this integration is available in the More detailed information about this integration is available in the
[LibreNMS integration module](../admin_guide/oss_bss/librenms.md). [LibreNMS integration module](../admin_guide/oss_bss/librenms.md).
### Kentik (planned) ### Kentik
Kentik is a Network Observability tool which collects various data points from deployed PE routers. Kentik is a Network Observability tool which collects various data points from deployed PE routers.
For this reason it is not in scope for PHASE1. For this reason it is not in scope for PHASE1.
### Inventory provider (planned) ### Inventory provider
At the time of writing, the Inventory Provider gets the list of routers from the network engineering SOT servers. At the time of writing, the Inventory Provider gets the list of routers from the network engineering SOT servers.
This will change and Inventory Provider is then able to directly query CoreDB. This will change and Inventory Provider is then able to directly query CoreDB.
## Interaction with a technical domain: IP/MPLS
TBA
...@@ -33,10 +33,10 @@ Microsoft.SentenceLength = NO ...@@ -33,10 +33,10 @@ Microsoft.SentenceLength = NO
; This statement ignores the names of parameters in docstrings, the four spaces that prepend it and the one following it ; This statement ignores the names of parameters in docstrings, the four spaces that prepend it and the one following it
; are necessary. ; are necessary.
TokenIgnores = \S+: TokenIgnores = (?: *\S+: ), (?:`\S+`)
[*.md] [*.md]
BasedOnStyles = Vale, proselint, Microsoft BasedOnStyles = Vale, proselint, Microsoft
[formats] [formats]
py = rst py = md
...@@ -11,6 +11,7 @@ CIDR ...@@ -11,6 +11,7 @@ CIDR
CFS CFS
CNAME CNAME
DCIM DCIM
DCN
DDI DDI
DHCP DHCP
DNS DNS
...@@ -90,3 +91,4 @@ WFO ...@@ -90,3 +91,4 @@ WFO
dry_run dry_run
eBGP eBGP
iBGP iBGP
disable?[sd]
"""Module that updates the domain model of GSO. Should contain all types of subscriptions. """Module that updates the domain model of GSO. Should contain all types of subscriptions.
.. warning:: !!! warning
Whenever a new product is added, this should be reflected in the `ProductType` enumerator. Whenever a new product is added, this should be reflected in the `ProductType` enumerator.
This does not hold for adding a new type of already existing product. This does not hold for adding a new type of already existing product.
""" """
from orchestrator.domain import SUBSCRIPTION_MODEL_REGISTRY from orchestrator.domain import SUBSCRIPTION_MODEL_REGISTRY
......
...@@ -131,17 +131,21 @@ class LanSwitchInterconnectBlockProvisioning( ...@@ -131,17 +131,21 @@ class LanSwitchInterconnectBlockProvisioning(
class LanSwitchInterconnectBlock(LanSwitchInterconnectBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class LanSwitchInterconnectBlock(LanSwitchInterconnectBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""A LAN Switch Interconnect that's currently deployed in the network.""" """A LAN Switch Interconnect that's currently deployed in the network.
Attributes:
lan_switch_interconnect_description: A human-readable description of this LAN Switch Interconnect.
minimum_links: The minimum amount of links the LAN Switch Interconnect should consist of.
switch_management_vlan_id: VLAN ID for the switch management network.
dcn_management_vlan_id: VLAN ID for the DCN management network, if the site of this product contains optical
equipment.
router_side: The router side of the LAN Switch Interconnect.
switch_side: The switch side of the LAN Switch Interconnect.
"""
#: A human-readable description of this LAN Switch Interconnect.
lan_switch_interconnect_description: str lan_switch_interconnect_description: str
#: The minimum amount of links the LAN Switch Interconnect should consist of.
minimum_links: int minimum_links: int
#: VLAN ID for the switch management network.
switch_management_vlan_id: VLAN_ID switch_management_vlan_id: VLAN_ID
#: VLAN ID for the DCN management network, if the site of this product contains optical equipment.
dcn_management_vlan_id: VLAN_ID | None dcn_management_vlan_id: VLAN_ID | None
#: The router side of the LAN Switch Interconnect.
router_side: LanSwitchInterconnectRouterSideBlock router_side: LanSwitchInterconnectRouterSideBlock
#: The switch side of the LAN Switch Interconnect.
switch_side: LanSwitchInterconnectSwitchSideBlock switch_side: LanSwitchInterconnectSwitchSideBlock
...@@ -31,21 +31,24 @@ class OpengearBlockProvisioning(OpengearBlockInactive, lifecycle=[SubscriptionLi ...@@ -31,21 +31,24 @@ class OpengearBlockProvisioning(OpengearBlockInactive, lifecycle=[SubscriptionLi
opengear_hostname: str opengear_hostname: str
opengear_site: SiteBlockProvisioning opengear_site: SiteBlockProvisioning
opengear_wan_address: ipaddress.IPv4Address | None = None opengear_wan_address: ipaddress.IPv4Address | None
opengear_wan_netmask: ipaddress.IPv4Address | None = None opengear_wan_netmask: ipaddress.IPv4Address | None
opengear_wan_gateway: ipaddress.IPv4Address | None = None opengear_wan_gateway: ipaddress.IPv4Address | None
class OpengearBlock(OpengearBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class OpengearBlock(OpengearBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""An Opengear that's currently deployed in the network.""" """An Opengear that's currently deployed in the network.
Attributes:
opengear_hostname: The hostname of the Opengear device.
opengear_site: The site where the Opengear device is located.
opengear_wan_address: The WAN address of the Opengear device.
opengear_wan_netmask: The WAN netmask of the Opengear device.
opengear_wan_gateway: The WAN gateway of the Opengear device.
"""
#: The hostname of the Opengear device.
opengear_hostname: str opengear_hostname: str
#: The site where the Opengear device is located.
opengear_site: SiteBlock opengear_site: SiteBlock
#: The WAN address of the Opengear device.
opengear_wan_address: ipaddress.IPv4Address opengear_wan_address: ipaddress.IPv4Address
#: The WAN netmask of the Opengear device.
opengear_wan_netmask: ipaddress.IPv4Address opengear_wan_netmask: ipaddress.IPv4Address
#: The WAN gateway of the Opengear device.
opengear_wan_gateway: ipaddress.IPv4Address opengear_wan_gateway: ipaddress.IPv4Address
...@@ -84,19 +84,22 @@ class PopVlanBlockProvisioning(PopVlanBlockInactive, lifecycle=[SubscriptionLife ...@@ -84,19 +84,22 @@ class PopVlanBlockProvisioning(PopVlanBlockInactive, lifecycle=[SubscriptionLife
class PopVlanBlock(PopVlanBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class PopVlanBlock(PopVlanBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""A Pop VLAN that's currently deployed in the network.""" """A Pop VLAN that's currently deployed in the network.
Attributes:
vlan_id: The VLAN ID of the Pop VLAN.
pop_vlan_description: The description of the Pop VLAN.
lan_switch_interconnect: The LAN Switch Interconnect that this Pop VLAN is connected to.
ports: The ports of the Pop VLAN.
layer_preference: The level of the layer preference for the Pop VLAN (L2 or L3).
ipv4_network: IPv4 network for the Pop VLAN if layer preference is L3.
ipv6_network: IPv6 network for the Pop VLAN if layer preference is L3.
"""
#: The VLAN ID of the Pop VLAN.
vlan_id: int vlan_id: int
#: The description of the Pop VLAN.
pop_vlan_description: str pop_vlan_description: str
#: The LAN Switch Interconnect that this Pop VLAN is connected to.
lan_switch_interconnect: LanSwitchInterconnectBlock lan_switch_interconnect: LanSwitchInterconnectBlock
#: The ports of the Pop VLAN.
ports: PortList[PopVlanPortBlock] # type: ignore[assignment] ports: PortList[PopVlanPortBlock] # type: ignore[assignment]
#: The level of the layer preference for the Pop VLAN (L2 or L3).
layer_preference: LayerPreference layer_preference: LayerPreference
#: IPv4 network for the Pop VLAN if layer preference is L3.
ipv4_network: IPv4Network | None ipv4_network: IPv4Network | None
#: IPv6 network for the Pop VLAN if layer preference is L3.
ipv6_network: IPv6Network | None ipv6_network: IPv6Network | None
...@@ -58,31 +58,35 @@ class SiteBlockProvisioning(SiteBlockInactive, lifecycle=[SubscriptionLifecycle. ...@@ -58,31 +58,35 @@ class SiteBlockProvisioning(SiteBlockInactive, lifecycle=[SubscriptionLifecycle.
class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""A site that's currently available for routers and services to be hosted at.""" """A site that's currently available for routers and services to be hosted at.
Attributes:
site_name: The name of the site, that will dictate part of the FQDN of routers that are hosted at this site. For
example: `router.X.Y.geant.net`, where X denotes the name of the site.
site_city: The city at which the site is located.
site_country: The country in which the site is located.
site_country_code: The code of the corresponding country. This is also used for the FQDN, following the example
given for the site name, the country code would end up in the Y position.
site_latitude: The latitude of the site, used for SNMP purposes.
site_longitude: Similar to the latitude, the longitude of a site.
site_internal_id: The internal ID used within GÉANT to denote a site.
site_bgp_community_id: The BGP community ID of a site, used to advertise routes learned at this site.
site_tier: The tier of a site, as described in `SiteTier`.
site_ts_address: 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.
site_contains_optical_equipment: Whether this site contains optical equipment, which dictates the need for a DCN
management VLAN.
"""
#: The name of the site, that will dictate part of the FQDN of routers that are hosted at this site. For
#: example: `router.X.Y.geant.net`, where X denotes the name of the site.
site_name: SiteName site_name: SiteName
#: The city at which the site is located.
site_city: str site_city: str
#: The country in which the site is located.
site_country: str site_country: str
#: The code of the corresponding country. This is also used for the FQDN, following the example given for
#: the site name, the country code would end up in the Y position.
site_country_code: str site_country_code: str
#: The latitude of the site, used for SNMP purposes.
site_latitude: LatitudeCoordinate site_latitude: LatitudeCoordinate
#: Similar to the latitude, the longitude of a site.
site_longitude: LongitudeCoordinate site_longitude: LongitudeCoordinate
#: The internal ID used within GÉANT to denote a site.
site_internal_id: int site_internal_id: int
#: The BGP community ID of a site, used to advertise routes learned at this site.
site_bgp_community_id: int site_bgp_community_id: int
#: The tier of a site, as described in `SiteTier`.
site_tier: SiteTier 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.
site_ts_address: IPAddress site_ts_address: IPAddress
#: Whether this site contains optical equipment, which dictates the need for a DCN management VLAN
site_contains_optical_equipment: bool site_contains_optical_equipment: bool
...@@ -23,29 +23,33 @@ class SuperPopSwitchBlockInactive( ...@@ -23,29 +23,33 @@ class SuperPopSwitchBlockInactive(
super_pop_switch_ts_port: PortNumber | None = None super_pop_switch_ts_port: PortNumber | None = None
super_pop_switch_mgmt_ipv4_address: IPv4AddressType | None = None super_pop_switch_mgmt_ipv4_address: IPv4AddressType | None = None
super_pop_switch_site: SiteBlockInactive | None super_pop_switch_site: SiteBlockInactive | None
vendor: Vendor | None = None vendor: Vendor | None = Vendor.JUNIPER
class SuperPopSwitchBlockProvisioning(SuperPopSwitchBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): class SuperPopSwitchBlockProvisioning(SuperPopSwitchBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
"""A Super PoP switch that's being provisioned. See `SuperPoPSwitchBlock`.""" """A Super PoP switch that's being provisioned. See `SuperPoPSwitchBlock`."""
super_pop_switch_fqdn: str | None = None super_pop_switch_fqdn: str | None
super_pop_switch_ts_port: PortNumber | None = None super_pop_switch_ts_port: PortNumber | None
super_pop_switch_mgmt_ipv4_address: IPv4AddressType | None = None super_pop_switch_mgmt_ipv4_address: IPv4AddressType | None
super_pop_switch_site: SiteBlockProvisioning | None super_pop_switch_site: SiteBlockProvisioning | None
vendor: Vendor | None = None vendor: Vendor | None
class SuperPopSwitchBlock(SuperPopSwitchBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): class SuperPopSwitchBlock(SuperPopSwitchBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
"""A Super PoP switch that's currently deployed in the network.""" """A Super PoP switch that's currently deployed in the network.
Attributes:
super_pop_switch_fqdn: Super PoP switch FQDN.
super_pop_switch_ts_port: The port of the terminal server that this Super PoP switch is connected to. Used to
offer out of band access.
super_pop_switch_mgmt_ipv4_address: The IPv4 management address of the Super PoP switch.
super_pop_switch_site: The `Site` that this Super PoP switch resides in. Both physically and computationally.
vendor: The vendor of a Super PoP switch. Defaults to Juniper.
"""
#: Super PoP switch FQDN.
super_pop_switch_fqdn: str super_pop_switch_fqdn: str
#: The port of the terminal server that this Super PoP switch is connected to. Used to offer out of band access.
super_pop_switch_ts_port: PortNumber super_pop_switch_ts_port: PortNumber
#: The IPv4 management address of the Super PoP switch.
super_pop_switch_mgmt_ipv4_address: IPv4AddressType super_pop_switch_mgmt_ipv4_address: IPv4AddressType
#: The `Site` that this Super PoP switch resides in. Both physically and computationally.
super_pop_switch_site: SiteBlock super_pop_switch_site: SiteBlock
#: The vendor of a Super PoP switch. Defaults to Juniper. vendor: Vendor
vendor: Vendor = Vendor.JUNIPER
...@@ -86,7 +86,7 @@ def create_v4_network_by_ip( ...@@ -86,7 +86,7 @@ def create_v4_network_by_ip(
"""Register an IPv4 network at the given location. """Register an IPv4 network at the given location.
Raises: Raises:
AllocationError on failure. AllocationError: on failure.
""" """
conn, _ = _setup_connection() conn, _ = _setup_connection()
created_net = objects.NetworkV4.create( created_net = objects.NetworkV4.create(
...@@ -105,7 +105,7 @@ def create_v6_network_by_ip( ...@@ -105,7 +105,7 @@ def create_v6_network_by_ip(
"""Register an IPv6 network at the given location. """Register an IPv6 network at the given location.
Raises: Raises:
AllocationError on failure. AllocationError: on failure.
""" """
conn, _ = _setup_connection() conn, _ = _setup_connection()
created_net = objects.NetworkV6.create( created_net = objects.NetworkV6.create(
...@@ -123,9 +123,9 @@ def hostname_available(hostname: str) -> bool: ...@@ -123,9 +123,9 @@ def hostname_available(hostname: str) -> bool:
Check whether Infoblox already has a ``infoblox_client.objects.HostRecord`` that matches the given hostname. Check whether Infoblox already has a ``infoblox_client.objects.HostRecord`` that matches the given hostname.
.. warning:: !!! danger
This method only checks within the Infoblox instance, and not the rest of the internet. The hostname could This method only checks within the Infoblox instance, and not the rest of the internet. The hostname could
therefore still be taken elsewhere. therefore still be taken elsewhere.
Args: Args:
hostname: The hostname to be checked. hostname: The hostname to be checked.
......
...@@ -101,10 +101,8 @@ class KentikClient: ...@@ -101,10 +101,8 @@ class KentikClient:
If the site is not found, return an empty dict. If the site is not found, return an empty dict.
.. vale off
Args: Args:
site_slug: The name of the site, should be a three-letter slug like COR or POZ. site_slug: The name of the site, should be a three-letter slug like `COR` or `POZ`.
""" """
sites = self.get_sites() sites = self.get_sites()
for site in sites: for site in sites:
...@@ -116,40 +114,42 @@ class KentikClient: ...@@ -116,40 +114,42 @@ class KentikClient:
def get_plans(self) -> list[dict[str, Any]]: def get_plans(self) -> list[dict[str, Any]]:
"""Get all Kentik plans available. """Get all Kentik plans available.
Returns a list of `plan` objects that each have the following shape:
<!-- vale off -->
```py
"plan": {
"active": true,
"bgp_enabled": true,
"cdate" "1970-01-01T01:01:01.000Z",
"company_id": 111111,
"description": "A description of this plan",
"deviceTypes": [
{"device_type": "router"},
{"device_type": "host-nprobe-dns-www"}
],
"devices": [
{
"id": "111111",
"device_name": "rt0.city.tld.internal",
"device_type": "router"
},
],
"edate": "2999-01-01T09:09:09.000Z",
"fast_retention": 10,
"full_retention": 5,
"id": 11111,
"max_bigdata_fps": 100,
"max_devices": 9001,
"max_fps": 200,
"name": "KENTIK-PLAN-01",
"metadata": {},
}
```
<!-- vale on -->
Returns: Returns:
a list of `plans` that each have the following shape: A list of plans configured in Kentik.
.. vale off
.. code-block:: json
"plan": {
"active": true,
"bgp_enabled": true,
"cdate" "1970-01-01T01:01:01.000Z",
"company_id": 111111,
"description": "A description of this plan",
"deviceTypes": [
{"device_type": "router"},
{"device_type": "host-nprobe-dns-www"}
],
"devices": [
{
"id": "111111",
"device_name": "rt0.city.tld.internal",
"device_type": "router"
},
],
"edate": "2999-01-01T09:09:09.000Z",
"fast_retention": 10,
"full_retention": 5,
"id": 11111,
"max_bigdata_fps": 100,
"max_devices": 9001,
"max_fps": 200,
"name": "KENTIK-PLAN-01",
"metadata": {},
}
.. vale on
""" """
return self._send_request("GET", "v5/plans")["plans"] return self._send_request("GET", "v5/plans")["plans"]
......
...@@ -73,37 +73,37 @@ def _execute_playbook( ...@@ -73,37 +73,37 @@ def _execute_playbook(
For example, an inventory consisting of two hosts, which each a unique host variable assigned to them looks as For example, an inventory consisting of two hosts, which each a unique host variable assigned to them looks as
follows: follows:
.. vale off ```py
.. code-block:: json "inventory": {
"all": {
"inventory": { "hosts": {
"all": { "host1.local": {
"hosts": { "foo": "bar"
"host1.local": { },
"foo": "bar" "host2.local": {
}, "key": "value"
"host2.local": { },
"key": "value" "host3.local": None
},
"host3.local": None
}
} }
} }
.. vale on }
```
.. warning:: !!! danger
Note the fact that the collection of all hosts is a dictionary, and not a list of strings. Ansible expects each Note the fact that the collection of all hosts is a dictionary, and not a list of strings. Ansible expects each
host to be a key-value pair. The key is the FQDN of a host, and the value always `null`. host to be a key-value pair. The key is the FQDN of a host, and the value always `null`.
The extra vars can be a simple dict consisting of key-value pairs, for example: The extra vars can be a simple dict consisting of key-value pairs, for example:
.. code-block:: json <!-- vale off -->
```py
"extra_vars": { "extra_vars": {
"dry_run": true, "dry_run": true,
"commit_comment": "I am a robot!", "commit_comment": "I am a robot!",
"verb": "deploy" "verb": "deploy"
} }
```
<!-- vale on -->
Args: Args:
playbook_name: Filename of the playbook that is to be executed. It must be present on the remote system running playbook_name: Filename of the playbook that is to be executed. It must be present on the remote system running
...@@ -111,7 +111,7 @@ def _execute_playbook( ...@@ -111,7 +111,7 @@ def _execute_playbook(
callback_route: The endpoint at which GSO expects a callback to continue the workflow executing this step. callback_route: The endpoint at which GSO expects a callback to continue the workflow executing this step.
inventory: An inventory of machines at which the playbook is targeted. Must be in YAML-compatible format. inventory: An inventory of machines at which the playbook is targeted. Must be in YAML-compatible format.
extra_vars: Any extra variables that the playbook relies on. This can include a subscription object, a boolean extra_vars: Any extra variables that the playbook relies on. This can include a subscription object, a boolean
value indicating a dry run, a commit comment, etc. All unicode character values are decoded to prevent value indicating a dry run, a commit comment, etc. All unicode character values are decoded to prevent
sending special characters to remote machines that don't support this. sending special characters to remote machines that don't support this.
""" """
parameters = { parameters = {
...@@ -169,7 +169,7 @@ def _clean_state() -> State: ...@@ -169,7 +169,7 @@ def _clean_state() -> State:
} }
def _inventory_is_set(state: State) -> bool: def validate_inventory_is_set(state: State) -> bool:
"""Validate whether the passed Ansible inventory is empty. """Validate whether the passed Ansible inventory is empty.
If the inventory is empty, which can happen in select cases, there should be no playbook run. This conditional will If the inventory is empty, which can happen in select cases, there should be no playbook run. This conditional will
...@@ -186,7 +186,7 @@ def _inventory_is_set(state: State) -> bool: ...@@ -186,7 +186,7 @@ def _inventory_is_set(state: State) -> bool:
return state["inventory"]["all"]["hosts"] return state["inventory"]["all"]["hosts"]
_inventory_is_not_empty = conditional(_inventory_is_set) _inventory_is_not_empty = conditional(validate_inventory_is_set)
def lso_interaction(provisioning_step: Step) -> StepList: def lso_interaction(provisioning_step: Step) -> StepList:
...@@ -228,9 +228,9 @@ def indifferent_lso_interaction(provisioning_step: Step) -> StepList: ...@@ -228,9 +228,9 @@ def indifferent_lso_interaction(provisioning_step: Step) -> StepList:
Whereas the `lso_interaction()` will make the workflow step fail on unsuccessful interaction, this step will not. Whereas the `lso_interaction()` will make the workflow step fail on unsuccessful interaction, this step will not.
It is therefore indifferent about the outcome of the Ansible playbook that is executed. It is therefore indifferent about the outcome of the Ansible playbook that is executed.
.. warning:: !!! danger
Using this interaction requires the operator to carefully evaluate the outcome of a playbook themselves. If a Using this interaction requires the operator to manually evaluate the outcome of a playbook. If a playbook
playbook fails, this will not cause the workflow to fail. fails, this will not cause the workflow to fail.
Args: Args:
provisioning_step: A workflow step that performs an operation remotely using the provisioning proxy. provisioning_step: A workflow step that performs an operation remotely using the provisioning proxy.
......
...@@ -319,7 +319,7 @@ class NetboxClient: ...@@ -319,7 +319,7 @@ class NetboxClient:
@staticmethod @staticmethod
def calculate_speed_bits_per_sec(speed: str) -> int: def calculate_speed_bits_per_sec(speed: str) -> int:
"""Extract the numeric part from the speed.""" """Calculate the numeric part from the speed."""
numeric_part = int("".join(filter(str.isdigit, speed))) numeric_part = int("".join(filter(str.isdigit, speed)))
# Convert to bits per second # Convert to bits per second
return numeric_part * 1000000 return numeric_part * 1000000
......
...@@ -129,9 +129,12 @@ class SNMPParams(BaseSettings): ...@@ -129,9 +129,12 @@ class SNMPParams(BaseSettings):
"""Parameters for SNMP in LibreNMS.""" """Parameters for SNMP in LibreNMS."""
v2c: MonitoringSNMPV2Params v2c: MonitoringSNMPV2Params
#: .. versionadded :: 2.0
#: Support for SNMP v3 will get added in a later version of GSO. Parameters are optional for now.
v3: MonitoringSNMPV3Params | None = None v3: MonitoringSNMPV3Params | None = None
"""
!!! example "Optional parameter"
Support for SNMP v3 will get added in a later version of GSO. Parameters are optional for now.
"""
class MonitoringParams(BaseSettings): class MonitoringParams(BaseSettings):
...@@ -157,7 +160,12 @@ class NetBoxParams(BaseSettings): ...@@ -157,7 +160,12 @@ class NetBoxParams(BaseSettings):
class EmailParams(BaseSettings): class EmailParams(BaseSettings):
"""Parameters for the email service.""" """Parameters for the email service.
Attributes:
notification_email_destinations: List of email addresses that should receive notifications when validation of a
subscription fails. Can be a comma-separated list of multiple addresses.
"""
from_address: EmailStr from_address: EmailStr
smtp_host: str smtp_host: str
...@@ -165,8 +173,6 @@ class EmailParams(BaseSettings): ...@@ -165,8 +173,6 @@ class EmailParams(BaseSettings):
starttls_enabled: bool starttls_enabled: bool
smtp_username: str | None = None smtp_username: str | None = None
smtp_password: str | None = None smtp_password: str | None = None
#: List of email addresses that should receive notifications when validation of a subscription fails.
#: Can be a comma-separated list of multiple addresses.
notification_email_destinations: str notification_email_destinations: str
......
...@@ -55,7 +55,7 @@ def check_netbox_entry_exists(subscription: Router) -> None: ...@@ -55,7 +55,7 @@ def check_netbox_entry_exists(subscription: Router) -> None:
@step("Verify P BGP P-ONLY neighbors") @step("Verify P BGP P-ONLY neighbors")
def verify_p_ibgp(subscription: dict[str, Any]) -> LSOState: def verify_p_ibgp(subscription: dict[str, Any]) -> LSOState:
"""Verify PE neighbors in P-ONLY group on a P router.""" """Verify PE neighbors in `P-ONLY` group on a P router."""
extra_vars = { extra_vars = {
"dry_run": True, "dry_run": True,
"subscription": subscription, "subscription": subscription,
...@@ -100,7 +100,7 @@ def verify_pe_mesh_in_pe(subscription: dict[str, Any]) -> LSOState: ...@@ -100,7 +100,7 @@ def verify_pe_mesh_in_pe(subscription: dict[str, Any]) -> LSOState:
@step("Verify PE BGP P-ONLY neighbors") @step("Verify PE BGP P-ONLY neighbors")
def verify_all_p_in_pe(subscription: dict[str, Any]) -> LSOState: def verify_all_p_in_pe(subscription: dict[str, Any]) -> LSOState:
"""Verify P neighbors in P-ONLY group on a PE router.""" """Verify P neighbors in `P-ONLY` group on a PE router."""
extra_vars = { extra_vars = {
"dry_run": True, "dry_run": True,
"subscription": subscription, "subscription": subscription,
......
"""A workflow for terminating a site subscription. """A workflow for terminating a site subscription.
The `terminate_site` workflow will take an existing and active site subscription from an `ACTIVE` to a `TERMINATED` The `terminate_site` workflow will take an existing and active site subscription from an `ACTIVE` to a `TERMINATED`
state. This requires all dependant subscription instances to already be terminated. If this is not the case, the state. This requires all dependant subscription instances to already be terminated. If not, the workflow will be
workflow will be unavailable for an operator to run, accompanied by an error message explaining this fact. unavailable for an operator to run, accompanied by an error message explaining this fact.
""" """
from orchestrator.forms import FormPage from orchestrator.forms import FormPage
......
"""A task that checks for all products in the database to be well-kept.""" """A task that checks for all products in the database to be well-kept."""
# .. vale off # <!-- vale off -->
# Copyright 2019-2020 SURF. # Copyright 2019-2020 SURF.
# Copyright 2024 GÉANT Vereniging. # Copyright 2024 GÉANT Vereniging.
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# .. vale on # <!-- vale on -->
from orchestrator.targets import Target from orchestrator.targets import Target
from orchestrator.workflow import StepList, done, init, workflow from orchestrator.workflow import StepList, done, init, workflow
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment