Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The provided methods and data models ensure easy handling, robust validation, co
### Prerequisites

- Access to a VideoIPath Server (version 2023.4.2 or higher, LTS versions recommended)
- A user account with API access credentials
- Username and Password for a user account with API access
- Python 3.11 or higher

### Installation
Expand All @@ -39,7 +39,7 @@ The package is available via the [Python Package Index (PyPI)](https://pypi.org/
#### Install the package using pip

```bash
pip3 install videoipath-automation-tool
pip install videoipath-automation-tool
```

### A Simple Example: Adding a Device to the Inventory
Expand All @@ -49,7 +49,7 @@ pip3 install videoipath-automation-tool
from videoipath_automation_tool import VideoIPathApp

# Initialize the VideoIPathApp
app = VideoIPathApp(server_address="10.1.100.10", username="api-user", password="veryStrongPassword")
app = VideoIPathApp(server_address="10.1.100.10", username="api-user", password="veryStrongPassword", use_https=False, verify_ssl_cert=False)

# Create a device object with NMOS Multidevice driver
staged_device = app.inventory.create_device(driver="com.nevion.NMOS_multidevice-0.1.0")
Expand Down
4 changes: 2 additions & 2 deletions docs/development-and-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ For stable/official versions, the common semver pattern is used:
For development versions, there are multiple options - since this package doesn't have a complex testing and verification process for release,
a simple format is used:

`<Major>.<Minor>.<Patch>.dev+<short commit SHA>`
`<Major>.<Minor>.<Patch>.dev<GitHub Action Run ID>`

Pip won't treat those versions as stable, they can only be installed by specifying the exact version or using the `--pre` flag.

Expand Down Expand Up @@ -71,7 +71,7 @@ flowchart TD
subgraph run-mr-pipeline["Run Merge-Request Pipeline"]
mr-tests["Run Tests [Pipeline]"]
mr-build["Build the Package [Pipeline]"]
publish-dev-version["Publish Dev Version, e.g. 1.3.6.dev+d882293d [Pipeline]"]
publish-dev-version["Publish Dev Version, e.g. 1.3.6.dev256 [Pipeline]"]

mr-tests --> mr-build
mr-build --> publish-dev-version
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "videoipath-automation-tool"
version = "0.1.6"
version = "0.2.0"
description = "A Python package for automating VideoIPath configuration workflows."
authors = ["Paul Winterstein <paul.winterstein@swr.de>"]
maintainers = ["SWR Media-over-IP Team <moip@swr.de>", "Josia Hildebrandt <manuel_josia.hildebrandt@swr.de>"]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional

from pydantic import BaseModel, Field

Expand Down Expand Up @@ -65,3 +65,30 @@ class DeviceStatus(BaseModel):
reachable: bool
softwareInfo: dict
url: str

def list_modules_label(self) -> List[str]:
"""List all modules label."""
return [module.label for module in self.modules]

def list_modules_id(self) -> List[str]:
"""List all modules id."""
return [module.id for module in self.modules]

def get_module_by_id(self, module_id: str) -> Optional[ModulesEntry]:
"""Get module by id."""
for module in self.modules:
if module.id == module_id:
return module
return None

def get_module_by_label(self, module_label: str) -> Optional[ModulesEntry]:
"""Returns the module with the specified label, or None if not found.

Raises:
ValueError: If multiple modules with the same label are found.
"""
matches = [module for module in self.modules if module.label == module_label]

if len(matches) > 1:
raise ValueError(f"Multiple modules found with label '{module_label}'")
return matches[0] if matches else None
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def add_virtual_module(self) -> GenericVertex:
"_vid": module_id,
"descriptor": {"label": "", "desc": ""},
"fDescriptor": {
"label": f"Virtual Device {device_number+1} Virtual Switching Core {module_number}",
"label": f"Virtual Device {device_number + 1} Virtual Switching Core {module_number}",
"desc": "",
},
"deviceId": f"{device_id}",
Expand Down Expand Up @@ -248,7 +248,7 @@ def add_virtual_codec_vertex(
"descriptor": {"label": "", "desc": ""},
"fDescriptor": {
"label": f"Vertex {vertex_number}",
"desc": f"Virtual Device {device_number+1} Vertex {vertex_number}",
"desc": f"Virtual Device {device_number + 1} Vertex {vertex_number}",
},
"deviceId": f"{device_id}",
"gpid": {
Expand Down Expand Up @@ -305,7 +305,7 @@ def add_virtual_codec_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Vertex {vertex_number} -> Virtual Device {device_number+1} Virtual Switching Core {module_number}",
"label": f"Vertex {vertex_number} -> Virtual Device {device_number + 1} Virtual Switching Core {module_number}",
"desc": "",
},
"fromId": f"{vertex_id}",
Expand All @@ -332,7 +332,7 @@ def add_virtual_codec_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Virtual Device {device_number+1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"label": f"Virtual Device {device_number + 1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"desc": "",
},
"fromId": f"{module_id}",
Expand Down Expand Up @@ -390,7 +390,7 @@ def add_virtual_ip_vertex(
"descriptor": {"label": "", "desc": ""},
"fDescriptor": {
"label": f"Vertex {vertex_number}",
"desc": f"Virtual Device {device_number+1} Vertex {vertex_number}",
"desc": f"Virtual Device {device_number + 1} Vertex {vertex_number}",
},
"deviceId": f"{device_id}",
"gpid": {
Expand Down Expand Up @@ -436,7 +436,7 @@ def add_virtual_ip_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Vertex {vertex_number} -> Virtual Device {device_number+1} Virtual Switching Core {module_number}",
"label": f"Vertex {vertex_number} -> Virtual Device {device_number + 1} Virtual Switching Core {module_number}",
"desc": "",
},
"fromId": f"{vertex_id}",
Expand All @@ -463,7 +463,7 @@ def add_virtual_ip_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Virtual Device {device_number+1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"label": f"Virtual Device {device_number + 1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"desc": "",
},
"fromId": f"{module_id}",
Expand Down Expand Up @@ -521,7 +521,7 @@ def add_virtual_generic_vertex(
"descriptor": {"label": "", "desc": ""},
"fDescriptor": {
"label": f"Vertex {vertex_number}",
"desc": f"Virtual Device {device_number+1} Vertex {vertex_number}",
"desc": f"Virtual Device {device_number + 1} Vertex {vertex_number}",
},
"deviceId": f"{device_id}",
"gpid": {
Expand Down Expand Up @@ -556,7 +556,7 @@ def add_virtual_generic_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Vertex {vertex_number} -> Virtual Device {device_number+1} Virtual Switching Core {module_number}",
"label": f"Vertex {vertex_number} -> Virtual Device {device_number + 1} Virtual Switching Core {module_number}",
"desc": "",
},
"fromId": f"{vertex_id}",
Expand All @@ -583,7 +583,7 @@ def add_virtual_generic_vertex(
"descriptor": {"label": "", "desc": ""},
"excludeFormats": [],
"fDescriptor": {
"label": f"Virtual Device {device_number+1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"label": f"Virtual Device {device_number + 1} Virtual Switching Core {module_number} -> Vertex {vertex_number}",
"desc": "",
},
"fromId": f"{module_id}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from pydantic import BaseModel, Field
from typing_extensions import deprecated

from videoipath_automation_tool.apps.inventory.model.device_status import DeviceStatus
from videoipath_automation_tool.apps.inventory.model.inventory_device import InventoryDevice
from videoipath_automation_tool.apps.topology.model.n_graph_elements.topology_base_device import BaseDevice
from videoipath_automation_tool.apps.topology.model.n_graph_elements.topology_codec_vertex import CodecVertex
from videoipath_automation_tool.apps.topology.model.n_graph_elements.topology_generic_vertex import GenericVertex
Expand Down Expand Up @@ -166,6 +168,78 @@ def site_id(self, value: str) -> None:
self.base_device.siteId = value

# --- Methods ---
def get_vertices_by_module_label(
self,
module_label: str,
inventory_device_status: InventoryDevice | DeviceStatus,
vertex_type: Literal["all", "codec_vertex", "ip_vertex", "generic_vertex"] = "all",
):
"""Get all vertices by module label.
Optionally, the search can be filtered by vertex type.

Args:
module_label (str): The module label to search for (e.g. `Slot 3`).
inventory_device_status (InventoryDevice | DeviceStatus): The inventory device status object.

Returns:
List[BaseDevice | GenericVertex | IpVertex | CodecVertex | UnidirectionalEdge]: A list of matching nGraphElements.
"""

if vertex_type == "all":
combined_vertex_list = chain(
self.generic_vertices,
self.ip_vertices,
self.codec_vertices,
) # Note: Base Device and Edges are not included in this search
elif vertex_type == "codec_vertex":
combined_vertex_list = self.codec_vertices
elif vertex_type == "ip_vertex":
combined_vertex_list = self.ip_vertices
elif vertex_type == "generic_vertex":
combined_vertex_list = self.generic_vertices
else:
raise ValueError(
f"Invalid vertex type: {vertex_type}. Valid options are 'all', 'codec_vertex', 'ip_vertex', or 'generic_vertex'."
)

if isinstance(inventory_device_status, InventoryDevice):
device_status = inventory_device_status
else:
device_status = inventory_device_status

if not device_status:
raise ValueError("Device status is not available.")

# Check if the device ID matches the topology device ID
if device_status.id != self.base_device.id:
raise ValueError(
f"Device ID mismatch: Inventory device ID '{device_status.id}' does not match topology device ID '{self.base_device.id}'."
)

module = device_status.get_module_by_label(module_label)

if not module:
raise ValueError(f"Module with label '{module_label}' not found in device status.")

# Build the list of element IDs to search for
# <device_id>.<module_id>.<port_id>
# e.g. 'device66.4.6200000'

element_id_list = []
device_id = device_status.id
module_id = module.id
for port in module.ports:
port_id = port.id
element_id = f"{device_id}.{module_id}.{port_id}"
element_id_list.append(element_id)

vertex_list = []
for element in combined_vertex_list:
if element.id in element_id_list:
vertex_list.append(element)

return vertex_list

def get_nGraphElement_by_id(
self, element_id: str
) -> Optional[BaseDevice | GenericVertex | IpVertex | CodecVertex | UnidirectionalEdge]:
Expand Down