Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Cisco OSPFv3 Model #377

Merged
merged 10 commits into from
Sep 22, 2023
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
2 changes: 1 addition & 1 deletion vmngclient/api/admin_tech_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def generate(
timeout=request_timeout,
)
except HTTPError as http_error:
response = http_error.response
response = http_error.response # type: ignore
if response.status_code == 200:
return response.json()["fileName"]
if response.status_code == 400 and create_admin_tech_error_msgs in response.json().get("error", {}).get(
Expand Down
29 changes: 22 additions & 7 deletions vmngclient/api/template_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from vmngclient.api.templates.models.cisco_ntp_model import CiscoNTPModel
from vmngclient.api.templates.models.cisco_omp_model import CiscoOMPModel
from vmngclient.api.templates.models.cisco_ospf import CiscoOSPFModel
from vmngclient.api.templates.models.cisco_ospfv3 import CiscoOspfv3Model
from vmngclient.api.templates.models.cisco_secure_internet_gateway import CiscoSecureInternetGatewayModel
from vmngclient.api.templates.models.cisco_snmp_model import CiscoSNMPModel
from vmngclient.api.templates.models.cisco_system import CiscoSystemModel
Expand Down Expand Up @@ -94,7 +95,10 @@ def get(self, template):
raise NotImplementedError()

def _get_feature_templates(
self, summary: bool = True, offset: Optional[int] = None, limit: Optional[int] = None
self,
summary: bool = True,
offset: Optional[int] = None,
limit: Optional[int] = None,
) -> DataSequence[FeatureTemplateInfo]:
"""In a multitenant vManage system, this API is only available in the Provider view."""
endpoint = "/dataservice/template/feature"
Expand Down Expand Up @@ -139,7 +143,11 @@ def _attach_feature(self, name: str, device: Device, **kwargs):
def get_device_specific_variables(name: str):
endpoint = "/dataservice/template/device/config/exportcsv"
template_id = self.get(DeviceTemplate).filter(name=name).single_or_default().id
body = {"templateId": template_id, "isEdited": False, "isMasterEdited": False}
body = {
"templateId": template_id,
"isEdited": False,
"isMasterEdited": False,
}

values = self.session.post(endpoint, json=body).json()["header"]["columns"]
return [DeviceSpecificValue(**value) for value in values]
Expand Down Expand Up @@ -454,7 +462,8 @@ def get_general_template_info(
return _template

def parse_general_template(
general_template: GeneralTemplate, fr_templates: DataSequence[FeatureTemplateInfo]
general_template: GeneralTemplate,
fr_templates: DataSequence[FeatureTemplateInfo],
) -> GeneralTemplate:
if general_template.subTemplates:
general_template.subTemplates = [
Expand Down Expand Up @@ -515,6 +524,7 @@ def is_created_by_generator(self, template: FeatureTemplate) -> bool:
CiscoOSPFModel,
CliTemplateModel,
CiscoSecureInternetGatewayModel,
CiscoOspfv3Model,
)

return isinstance(template, ported_templates)
Expand Down Expand Up @@ -560,9 +570,9 @@ def generate_feature_template_payload(
value = template.device_specific_variables[field.key]
else:
for field_name, field_value in template.__fields__.items():
if (
field.dataPath == field_value.field_info.extra.get("data_path", []) # type: ignore
and field.key == field_value.alias
if field.dataPath == field_value.field_info.extra.get("data_path", []) and ( # type: ignore
field.key == field_value.alias
or field.key == field_value.field_info.extra.get("vmanage_key") # type: ignore
):
value = getattr(template, field_name)
break
Expand Down Expand Up @@ -668,7 +678,12 @@ def edit_before_push(self, name: str, device: Device) -> bool:
error_details = json.loads(error.response.text)
logger.error(f"Error in config: {error_details['error']['details']}.")
return False
payload = {"templateId": template_id, "deviceIds": [device.uuid], "isEdited": True, "isMasterEdited": True}
payload = {
"templateId": template_id,
"deviceIds": [device.uuid],
"isEdited": True,
"isMasterEdited": True,
}
endpoint = "/dataservice/template/device/config/input/"
logger.info(f"Editing template: {name} of device: {device.hostname}.")
response = self.session.post(url=endpoint, json=payload).json()
Expand Down
4 changes: 3 additions & 1 deletion vmngclient/api/templates/feature_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ def remove_device_variables(cls, values):
values["device_specific_variables"] = {}
to_delete = {}

# TODO: Add support for nested models with DeviceVariable
for key, value in values.items():
if isinstance(value, DeviceVariable):
to_delete[key] = value
values["device_specific_variables"][cls.__fields__[key].alias] = DeviceVariable(name=value.name)
field_key = cls.__fields__[key].field_info.extra.get("vmanage_key", cls.__fields__[key].alias)
values["device_specific_variables"][field_key] = DeviceVariable(name=value.name)

for var in to_delete:
if var in values:
Expand Down
2 changes: 1 addition & 1 deletion vmngclient/api/templates/feature_template_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def nest_value_in_output(value: Any) -> dict:
model_field: ModelField = next(
filter(
lambda f: f.field_info.extra.get("data_path", []) == child.dataPath
and f.alias == child.key,
and (f.alias == child.key or f.field_info.extra.get("vmanage_key") == child.key),
obj.__fields__.values(),
)
)
Expand Down
30 changes: 15 additions & 15 deletions vmngclient/api/templates/models/cisco_aaa_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,32 @@ class User(BaseModel):
password: str
secret: str
privilege: Optional[str]
pubkey_chain: List[str] = Field(default=[], alias="pubkey-chain")
pubkey_chain: List[str] = Field(default=[], vmanage_key="pubkey-chain")


class RadiusServer(BaseModel):
class Config:
allow_population_by_field_name = True

address: str
auth_port: int = Field(alias="auth-port", default=1812)
acct_port: int = Field(alias="acct-port", default=1813)
auth_port: int = Field(vmanage_key="auth-port", default=1812)
acct_port: int = Field(vmanage_key="acct-port", default=1813)
timeout: int = Field(default=5)
retransmit: int = 3
key: str
secret_key: Optional[str] = Field(alias="secret-key", default=None)
key_enum: Optional[str] = Field(alias="key-enum", default=None)
key_type: Optional[str] = Field(alias="key-type", default=None)
secret_key: Optional[str] = Field(vmanage_key="secret-key", default=None)
key_enum: Optional[str] = Field(vmanage_key="key-enum", default=None)
key_type: Optional[str] = Field(vmanage_key="key-type", default=None)


class RadiusGroup(BaseModel):
class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

group_name: str = Field(alias="group-name")
group_name: str = Field(vmanage_key="group-name")
vpn: Optional[int]
source_interface: Optional[str] = Field(alias="source-interface")
source_interface: Optional[str] = Field(vmanage_key="source-interface")
server: List[RadiusServer] = []


Expand All @@ -55,17 +55,17 @@ class Config:
port: int = 49
timeout: int = Field(default=5)
key: str
secret_key: Optional[str] = Field(alias="secret-key", default=None)
key_enum: Optional[str] = Field(alias="key-enum", default=None)
secret_key: Optional[str] = Field(vmanage_key="secret-key", default=None)
key_enum: Optional[str] = Field(vmanage_key="key-enum", default=None)


class TacacsGroup(BaseModel):
class Config:
allow_population_by_field_name = True

group_name: str = Field(alias="group-name")
group_name: str = Field(vmanage_key="group-name")
vpn: int = 0
source_interface: Optional[str] = Field(alias="source-interface", default=None)
source_interface: Optional[str] = Field(vmanage_key="source-interface", default=None)
server: List[TacacsServer] = []


Expand All @@ -75,13 +75,13 @@ class Config:
allow_population_by_field_name = True

user: List[User] = []
authentication_group: bool = Field(alias="authentication_group", default=False)
authentication_group: bool = Field(vmanage_key="authentication_group", default=False)
accounting_group: bool = True
radius: List[RadiusGroup] = []
domain_stripping: Optional[DomainStripping] = Field(alias="domain-stripping", default=None)
domain_stripping: Optional[DomainStripping] = Field(vmanage_key="domain-stripping", default=None)
port: int = 1700
tacacs: List[TacacsGroup] = []
server_auth_order: str = Field(alias="server-auth-order", default="local")
server_auth_order: str = Field(vmanage_key="server-auth-order", default="local")

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
type: ClassVar[str] = "cedge_aaa"
4 changes: 2 additions & 2 deletions vmngclient/api/templates/models/cisco_banner_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Config:
arbitrary_types_allowed = True
allow_population_by_field_name = True

login_banner: Optional[str] = Field(alias="login")
motd_banner: Optional[str] = Field(alias="motd")
login_banner: Optional[str] = Field(vmanage_key="login")
motd_banner: Optional[str] = Field(vmanage_key="motd")

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
type: ClassVar[str] = "cisco_banner"
10 changes: 6 additions & 4 deletions vmngclient/api/templates/models/cisco_bfd_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ class ColorType(str, Enum):

class Color(ConvertBoolToStringModel):
color: ColorType
hello_interval: Optional[int] = Field(DEFAULT_BFD_HELLO_INTERVAL, alias="hello-interval")
hello_interval: Optional[int] = Field(DEFAULT_BFD_HELLO_INTERVAL, vmanage_key="hello-interval")
multiplier: Optional[int] = DEFAULT_BFD_COLOR_MULTIPLIER
pmtu_discovery: Optional[bool] = Field(True, alias="pmtu-discovery")
pmtu_discovery: Optional[bool] = Field(True, vmanage_key="pmtu-discovery")
dscp: Optional[int] = DEFAULT_BFD_DSCP

class Config:
Expand All @@ -56,8 +56,10 @@ class Config:
allow_population_by_field_name = True

multiplier: Optional[int] = Field(DEFAULT_BFD_MULTIPLIER, data_path=["app-route"])
poll_interval: Optional[int] = Field(DEFAULT_BFD_POLL_INTERVAL, alias="poll-interval", data_path=["app-route"])
default_dscp: Optional[int] = Field(DEFAULT_BFD_DSCP, alias="default-dscp")
poll_interval: Optional[int] = Field(
DEFAULT_BFD_POLL_INTERVAL, vmanage_key="poll-interval", data_path=["app-route"]
)
default_dscp: Optional[int] = Field(DEFAULT_BFD_DSCP, vmanage_key="default-dscp")
color: Optional[List[Color]]

payload_path: ClassVar[Path] = Path(__file__).parent / "DEPRECATED"
Expand Down
Loading