Beispiel #1
0
class ViewPlanForm(BaseForm):
    form_type = HiddenField(default="plan")
    action = "eNMS.viewBuilder.createPlan"
    name = StringField("Name", [InputRequired()])
    size = IntegerField("Size", default=2000)
    rows = IntegerField("Number of Rows", default=100)
    opacity = FloatField("Opacity", default=1.0)
class GenericFileTransferForm(ServiceForm):
    form_type = HiddenField(default="generic_file_transfer_service")
    direction = SelectField(choices=(("get", "Get"), ("put", "Put")))
    protocol = SelectField(choices=(("scp", "SCP"), ("sftp", "SFTP")))
    source_file = StringField(validators=[InputRequired()], substitution=True)
    destination_file = StringField(validators=[InputRequired()],
                                   substitution=True)
    missing_host_key_policy = BooleanField()
    load_known_host_keys = BooleanField()
    source_file_includes_globbing = BooleanField(
        "Source file includes glob pattern")
    max_transfer_size = IntegerField(default=2**30)
    window_size = IntegerField(default=2**30)
    timeout = FloatField(default=10.0)
    credentials = SelectField(
        "Credentials",
        choices=(
            ("device", "Device Credentials"),
            ("user", "User Credentials"),
            ("custom", "Custom Credentials"),
        ),
    )
    custom_username = StringField("Custom Username", substitution=True)
    custom_password = PasswordField("Custom Password", substitution=True)

    def validate(self):
        valid_form = super().validate()
        invalid_direction = (self.source_file_includes_globbing.data
                             and self.direction.data == "get")
        if invalid_direction:
            self.direction.errors.append(
                "Globbing only works with the 'PUT' direction")
        return valid_form and not invalid_direction
Beispiel #3
0
class DeviceForm(ObjectForm):
    form_type = HiddenField(default="device")
    icon = SelectField(
        "Icon",
        choices=(
            ("antenna", "Antenna"),
            ("firewall", "Firewall"),
            ("host", "Host"),
            ("optical_switch", "Optical switch"),
            ("regenerator", "Regenerator"),
            ("router", "Router"),
            ("server", "Server"),
            ("switch", "Switch"),
        ),
    )
    ip_address = StringField("IP address")
    port = IntegerField("Port", default=22)
    operating_system = StringField("Operating System")
    os_version = StringField("OS Version")
    longitude = StringField("Longitude", default=0.0)
    latitude = StringField("Latitude", default=0.0)
    napalm_driver = SelectField("NAPALM Driver",
                                choices=vs.napalm_drivers,
                                default="ios")
    netmiko_driver = SelectField("Netmiko Driver",
                                 choices=vs.netmiko_drivers,
                                 default="cisco_ios")
    scrapli_driver = SelectField(
        "Scrapli Driver",
        choices=vs.dualize(vs.scrapli_drivers),
        default="cisco_iosxe",
    )
    netconf_driver = SelectField("Netconf Driver",
                                 choices=vs.netconf_drivers,
                                 default="default")
Beispiel #4
0
class PingForm(ServiceForm):
    form_type = HiddenField(default="ping_service")
    protocol = SelectField(choices=(("ICMP", "ICMP Ping"), ("TCP",
                                                            "TCP Ping")))
    ports = StringField("Ports (TCP ping only)", default=22)
    count = IntegerField(default=5)
    timeout = IntegerField(default=2)
    ttl = IntegerField(default=60)
    packet_size = IntegerField(default=56)

    def validate(self):
        valid_form = super().validate()
        invalid_tcp_port = self.protocol.data == "TCP" and not self.ports.data
        if invalid_tcp_port:
            self.ports.errors.append("You must enter a port for a TCP ping.")
        return valid_form and not invalid_tcp_port
Beispiel #5
0
class ServerForm(BaseForm):
    action = "eNMS.base.processData"
    form_type = HiddenField(default="server")
    id = HiddenField()
    name = StringField("Name", [InputRequired()])
    description = StringField(widget=TextArea(), render_kw={"rows": 6})
    ip_address = StringField("IP address")
    weight = IntegerField("Weigth", default=1)
Beispiel #6
0
class ConfigureBgpForm(NapalmForm):
    form_type = HiddenField(default="configure_bgp_service")
    local_as = IntegerField("Local AS", default=0)
    loopback = StringField("Loopback", default="Lo42")
    loopback_ip = StringField("Loopback IP")
    neighbor_ip = StringField("Neighbor IP")
    remote_as = IntegerField("Remote AS")
    vrf_name = StringField("VRF Name")
    groups = {
        "Main Parameters": {
            "commands": [
                "local_as",
                "loopback",
                "loopback_ip",
                "neighbor_ip",
                "remote_as",
                "vrf_name",
            ],
            "default": "expanded",
        },
        **NapalmForm.groups,
    }
Beispiel #7
0
class TaskForm(BaseForm):
    action = "eNMS.base.processData"
    form_type = HiddenField(default="task")
    id = HiddenField()
    name = StringField("Name", [InputRequired()])
    default_access = SelectField(choices=(
        ("creator", "Creator only"),
        ("public", "Public (all users)"),
        ("admin", "Admin Users only"),
    ))
    scheduling_mode = SelectField(
        "Scheduling Mode",
        choices=(("cron", "Crontab Scheduling"), ("standard",
                                                  "Standard Scheduling")),
    )
    description = StringField("Description")
    start_date = StringField("Start Date", type="date")
    end_date = StringField("End Date", type="date")
    frequency = IntegerField("Frequency", default=0)
    frequency_unit = SelectField(
        "Frequency Unit",
        choices=(
            ("seconds", "Seconds"),
            ("minutes", "Minutes"),
            ("hours", "Hours"),
            ("days", "Days"),
        ),
    )
    crontab_expression = StringField("Crontab Expression")
    initial_payload = DictField("Payload")
    devices = MultipleInstanceField("Devices", model="device")
    pools = MultipleInstanceField("Pools", model="pool")
    service = InstanceField("Service", model="service")

    def validate(self):
        valid_form = super().validate()
        if self.name.data == "Bulk Edit":
            return valid_form
        no_date = self.scheduling_mode.data == "standard" and not self.start_date.data
        if no_date:
            self.start_date.errors.append("A start date must be set.")
        no_cron_expression = (self.scheduling_mode.data == "cron"
                              and not self.crontab_expression.data)
        if no_cron_expression:
            self.crontab_expression.errors.append(
                "A crontab expression must be set.")
        no_service = not self.service.data
        if no_service:
            self.service.errors.append("No service set.")
        return valid_form and not any(
            [no_date, no_cron_expression, no_service])
Beispiel #8
0
class NapalmTracerouteForm(NapalmForm):
    form_type = HiddenField(default="napalm_traceroute_service")
    destination_ip = StringField(substitution=True)
    source_ip = StringField(substitution=True)
    ttl = IntegerField(default=255)
    vrf = StringField()
    groups = {
        "Traceroute Parameters": {
            "commands":
            ["destination_ip", "source_ip", "timeout", "ttl", "vrf"],
            "default": "expanded",
        },
        **NapalmForm.groups,
    }
Beispiel #9
0
class NapalmPingForm(NapalmForm):
    form_type = HiddenField(default="napalm_ping_service")
    count = IntegerField(default=5)
    packet_size = IntegerField(default=100)
    destination_ip = StringField(substitution=True)
    source_ip = StringField(substitution=True)
    timeout = IntegerField(default=2)
    ttl = IntegerField(default=255)
    vrf = StringField()
    groups = {
        "Ping Parameters": {
            "commands": [
                "count",
                "packet_size",
                "destination_ip",
                "source_ip",
                "timeout",
                "ttl",
                "vrf",
            ],
            "default": "expanded",
        },
        **NapalmForm.groups,
    }
Beispiel #10
0
class NapalmForm(ConnectionForm):
    form_type = HiddenField(default="napalm")
    get_request_allowed = False
    abstract_service = True
    driver = SelectField(choices=vs.napalm_drivers)
    use_device_driver = BooleanField(
        default=True,
        help="common/use_device_driver",
    )
    timeout = IntegerField(default=10)
    optional_args = DictField()
    groups = {
        "Napalm Parameters": {
            "commands":
            ["driver", "use_device_driver", "timeout", "optional_args"],
            "default": "expanded",
        },
        **ConnectionForm.groups,
    }
Beispiel #11
0
class CredentialForm(BaseForm):
    action = "eNMS.base.processData"
    form_type = HiddenField(default="credential")
    id = HiddenField()
    name = StringField("Name", [InputRequired()])
    description = StringField(widget=TextArea(), render_kw={"rows": 6})
    role = SelectField(
        "Role",
        choices=(
            ("read-write", "Read Write"),
            ("read-only", "Read Only"),
        ),
    )
    subtype = SelectField(
        "Subtype",
        choices=(("password", "Username / Password"), ("key", "SSH Key")),
    )
    device_pools = MultipleInstanceField("Devices", model="pool")
    user_pools = MultipleInstanceField("Users", model="pool")
    priority = IntegerField("Priority", default=1)
    username = StringField("Username")
    password = PasswordField("Password")
    private_key = StringField(widget=TextArea(), render_kw={"rows": 1})
    enable_password = PasswordField("'Enable' Password")
Beispiel #12
0
class ServiceForm(BaseForm):
    template = "service"
    form_type = HiddenField(default="service")
    get_request_allowed = False
    id = HiddenField()
    name = StringField("Name")
    type = StringField("Service Type")
    access_groups = StringField("Groups")
    shared = BooleanField("Shared")
    scoped_name = StringField("Scoped Name", [InputRequired()])
    description = StringField("Description")
    device_query = StringField("Device Query",
                               python=True,
                               widget=TextArea(),
                               render_kw={"rows": 2})
    device_query_property = SelectField("Query Property Type",
                                        choices=(("name", "Name"),
                                                 ("ip_address", "IP address")))
    target_devices = MultipleInstanceField("Devices", model="device")
    disable_result_creation = BooleanField("Save only failed results")
    target_pools = MultipleInstanceField("Pools", model="pool")
    update_target_pools = BooleanField("Update target pools before running")
    update_pools_after_running = BooleanField("Update pools after running")
    workflows = MultipleInstanceField("Workflows", model="workflow")
    owners = MultipleInstanceField("Owners", model="user")
    owners_access = SelectMultipleStringField(
        "Owners Access",
        choices=[("run", "Run"), ("edit", "Edit")],
    )
    waiting_time = IntegerField(
        "Time to Wait before next service is started (in seconds)", default=0)
    priority = IntegerField("Priority", default=1)
    send_notification = BooleanField("Send a notification")
    send_notification_method = SelectField(
        "Notification Method",
        choices=(("mail", "Mail"), ("slack", "Slack"), ("mattermost",
                                                        "Mattermost")),
    )
    notification_header = StringField(widget=TextArea(),
                                      render_kw={"rows": 5},
                                      substitution=True)
    include_device_results = BooleanField("Include Device Results")
    include_link_in_summary = BooleanField("Include Result Link in Summary")
    display_only_failed_nodes = BooleanField("Display only Failed Devices")
    mail_recipient = StringField("Mail Recipients (separated by comma)")
    reply_to = StringField("Reply-to Email Address")
    number_of_retries = IntegerField("Number of retries", default=0)
    time_between_retries = IntegerField("Time between retries (in seconds)",
                                        default=10)
    max_number_of_retries = IntegerField("Maximum number of retries",
                                         default=100)
    credential_type = SelectField(
        "Type of Credentials",
        choices=(
            ("any", "Any"),
            ("read-write", "Read Write"),
            ("read-only", "Read Only"),
        ),
    )
    maximum_runs = IntegerField("Maximum number of runs", default=1)
    skip_query = StringField("Skip Query (Python)",
                             python=True,
                             widget=TextArea(),
                             render_kw={"rows": 2})
    skip_value = SelectField(
        "Skip Value",
        choices=(
            ("success", "Success"),
            ("failure", "Failure"),
            ("discard", "Discard"),
        ),
    )
    vendor = StringField("Vendor")
    operating_system = StringField("Operating System")
    iteration_values = StringField("Iteration Values", python=True)
    initial_payload = DictField()
    mandatory_parametrization = BooleanField("Parameterized Form is Mandatory")
    parameterized_form = StringField(
        type="code",
        python=True,
        widget=TextArea(),
        default="\n".join(vs.automation["parameterized_form"]),
    )
    iteration_variable_name = StringField("Iteration Variable Name",
                                          default="iteration_value")
    iteration_devices = StringField("Iteration Devices", python=True)
    iteration_devices_property = SelectField(
        "Iteration Devices Property",
        choices=(("name", "Name"), ("ip_address", "IP address")),
    )
    preprocessing = StringField(type="code", python=True, widget=TextArea())
    postprocessing = StringField(type="code", python=True, widget=TextArea())
    postprocessing_mode = SelectField(choices=(
        ("success", "Run on success only"),
        ("failure", "Run on failure only"),
        ("always", "Always run"),
    ))
    default_access = SelectField(choices=(
        ("creator", "Role Based (Creator)"),
        ("public", "Public (All users)"),
        ("admin", "Admin (Admins only"),
    ))
    log_level = SelectField(
        "Logging",
        choices=((0, "Disable logging"), *enumerate(vs.log_levels, 1)),
        default=1,
    )
    multiprocessing = BooleanField("Multiprocessing")
    max_processes = IntegerField("Maximum number of processes", default=15)
    validation_condition = SelectField(choices=(
        ("none", "No validation"),
        ("success", "Run on success only"),
        ("failure", "Run on failure only"),
        ("always", "Always run"),
    ))
    conversion_method = SelectField(choices=(
        ("none", "No conversion"),
        ("text", "Text"),
        ("json", "Json dictionary"),
        ("xml", "XML dictionary"),
    ))
    validation_method = SelectField(
        "Validation Method",
        choices=(
            ("text", "Validation by text match"),
            ("dict_included", "Validation by dictionary inclusion"),
            ("dict_equal", "Validation by dictionary equality"),
        ),
    )
    validation_section = StringField("Section to Validate",
                                     default="results['result']")
    content_match = StringField("Content Match",
                                widget=TextArea(),
                                render_kw={"rows": 8},
                                substitution=True)
    content_match_regex = BooleanField(
        '"Content Match" is a regular expression')
    dict_match = DictField("Dictionary to Match Against", substitution=True)
    negative_logic = BooleanField("Negative logic")
    delete_spaces_before_matching = BooleanField(
        "Delete Spaces before Matching")
    run_method = SelectField(
        "Run Method",
        choices=(
            ("per_device", "Run the service once per device"),
            ("once", "Run the service once"),
        ),
    )

    def validate(self):
        valid_form = super().validate()
        no_recipient_error = (self.send_notification.data
                              and self.send_notification_method.data == "mail"
                              and not self.mail_recipient.data)
        if no_recipient_error:
            self.mail_recipient.errors.append(
                "Please add at least one recipient for the mail notification.")
        forbidden_name_error = self.scoped_name.data in ("Start", "End",
                                                         "Placeholder")
        if forbidden_name_error:
            self.name.errors.append("This name is not allowed.")
        conversion_validation_mismatch = self.validation_condition.data != "none" and (
            self.conversion_method.data == "text"
            and "dict" in self.validation_method.data
            or self.conversion_method.data in ("xml", "json")
            and "dict" not in self.validation_method.data)
        if conversion_validation_mismatch:
            self.conversion_method.errors.append(
                f"The conversion method is set to {self.conversion_method.data}"
                f" and the validation method to {self.validation_method.data} :"
                " these do not match.")
        empty_validation = self.validation_condition.data != "none" and (
            self.validation_method.data == "text"
            and not self.content_match.data or self.validation_method.data
            == "dict_included" and self.dict_match.data == "{}")
        if empty_validation:
            self.content_match.errors.append(
                f"The validation method is set to '{self.validation_method.data}'"
                f" and the matching value is empty: these do no match.")
        too_many_threads_error = (self.max_processes.data >
                                  vs.settings["automation"]["max_process"])
        if too_many_threads_error:
            self.max_processes.errors.append(
                "The number of threads used for multiprocessing must be "
                f"less than {vs.settings['automation']['max_process']}.")
        shared_service_error = not self.shared.data and len(
            self.workflows.data) > 1
        if shared_service_error:
            self.shared.errors.append(
                "The 'shared' property is unticked, but the service belongs"
                " to more than one workflow: this is incompatible.")
        return (valid_form and not conversion_validation_mismatch
                and not empty_validation and not forbidden_name_error
                and not no_recipient_error and not shared_service_error
                and not too_many_threads_error)
Beispiel #13
0
class ExampleForm(ServiceForm):
    # Each service model must have an corresponding form.
    # The purpose of a form is twofold:
    # - Define how the service is displayed in the UI
    # - Check for each field that the user input is valid.
    # A service cannot be created/updated until all fields are validated.

    # The following line is mandatory: the default value must point
    # to the service.
    form_type = HiddenField(default="example_service")

    # string1 is defined as a "SelectField": it will be displayed as a
    # drop-down list in the UI.
    string1 = SelectField(
        choices=[("cisco", "Cisco"), ("juniper", "Juniper"), ("arista", "Arista")]
    )

    # String2 is a StringField, which is displayed as a standard textbox.
    # The "InputRequired" validator is used: this field is mandatory.
    string2 = StringField("String 2 (required)", [InputRequired()])

    # The main address length must be comprised between 7 and 25 characters
    mail_address = StringField("Mail address", [Length(min=7, max=25)])

    # This IP address validator will ensure the user input is a valid IPv4 address.
    # If it isn't, you can set the error message to be displayed in the GUI.
    ip_address = StringField(
        "IP address",
        [
            IPAddress(
                ipv4=True,
                message="Please enter an IPv4 address for the IP address field",
            )
        ],
    )

    # MAC address validator
    mac_address = StringField("MAC address", [MacAddress()])

    # The NumberRange validator will ensure the user input is an integer
    # between 3 and 8.
    number_in_range = IntegerField("Number in range", [NumberRange(min=3, max=8)])

    # The Regexp field will ensure the user input matches the regular expression.
    regex = StringField("Regular expression", [Regexp(r".*")])

    # URL validation, with or without TLD.
    url = StringField(
        "URL",
        [
            URL(
                require_tld=True,
                message="An URL with TLD is required for the url field",
            )
        ],
    )

    # The NoneOf validator lets you define forbidden value for a field.
    exclusion_field = StringField(
        "Exclusion field",
        [
            NoneOf(
                ("a", "b", "c"),
                message=(
                    "'a', 'b', and 'c' are not valid " "inputs for the exclusion field"
                ),
            )
        ],
    )
    an_integer = IntegerField()
    a_float = FloatField()

    # If validator the user input is more complex, you can create a python function
    # to implement the validation mechanism.
    # Here, the custom_integer field will be validated by the "validate_custom_integer"
    # function below.
    # That function will check that the custom integer value is superior to the product
    # of "an_integer" and "a_float".
    # You must raise a "ValidationError" when the validation fails.
    custom_integer = IntegerField("Custom Integer")

    # A SelectMultipleField will be displayed as a drop-down list that allows
    # multiple selection.
    a_list = SelectMultipleField(
        choices=[("value1", "Value 1"), ("value2", "Value 2"), ("value3", "Value 3")]
    )
    a_dict = DictField()

    # A BooleanField is displayed as a check box.
    boolean1 = BooleanField()
    boolean2 = BooleanField("Boolean N°1")

    def validate_custom_integer(self, field):
        product = self.an_integer.data * self.a_float.data
        if field.data > product:
            raise ValidationError(
                "Custom integer must be less than the "
                "product of 'An integer' and 'A float'"
            )
Beispiel #14
0
class NetconfForm(ConnectionForm):
    form_type = HiddenField(default="netconf_service")
    nc_type = SelectField(
        choices=(
            ("get_config", "Get Full Config"),
            ("get_filtered_config", "Get"),
            ("push_config", "Edit Config"),
            ("copy_config", "Copy Config"),
            ("rpc", "Dispatch"),
        ),
        label="NETCONF Operation",
    )
    xml_filter = StringField(label="XML Filter",
                             widget=TextArea(),
                             render_kw={"rows": 5},
                             substitution=True)
    target = SelectField(
        choices=(
            ("running", "Running"),
            ("candidate", "Candidate"),
            ("startup", "Startup"),
        ),
        label="Target Config",
    )
    default_operation = SelectField(
        choices=(
            ("merge", "Merge"),
            ("replace", "Replace"),
            ("None", "None"),
        ),
        label="Default config operation",
        validate_choice=False,
    )
    test_option = SelectField(
        choices=(
            ("test-then-set", "Test, then set"),
            ("set", "Set"),
            ("None", "None"),
        ),
        label="Config test option",
        validate_choice=False,
    )
    error_option = SelectField(
        choices=(
            ("stop-on-error", "Stop on error"),
            ("continue-on-error", "Continue on error"),
            ("rollback-on-error", "Rollback on error"),
            ("None", "None"),
        ),
        label="Error option",
        validate_choice=False,
    )
    lock = BooleanField(label="Lock target")
    unlock = BooleanField(label="Unlock target")
    copy_source = SelectField(
        choices=(
            ("running", "Running"),
            ("candidate", "Candidate"),
            ("startup", "Startup"),
            ("source_url", "Source URL"),
        ),
        label="Copy Source",
        validate_choice=False,
    )
    source_url = StringField(
        label="Copy source URL",
        widget=TextArea(),
        render_kw={"rows": 1},
        substitution=True,
    )
    copy_destination = SelectField(
        choices=(
            ("running", "Running"),
            ("candidate", "Candidate"),
            ("startup", "Startup"),
            ("destination_url", "Destination URL"),
        ),
        label="Copy Destination",
        validate_choice=False,
    )
    destination_url = StringField(
        label="Copy destination URL",
        widget=TextArea(),
        render_kw={"rows": 1},
        substitution=True,
    )
    commit_conf = BooleanField(label="Commit")
    timeout = IntegerField(default=15)
    xml_conversion = BooleanField(label="Convert XML result to dictionary",
                                  default=True)

    @classmethod
    def form_init(cls):
        parameters = {
            "get_config": ["target", "xml_conversion"],
            "get_filtered_config": [
                "target",
                "xml_filter",
                "xml_conversion",
            ],
            "push_config": [
                "target",
                "xml_filter",
                "default_operation",
                "test_option",
                "error_option",
                "lock",
                "unlock",
                "commit_conf",
                "xml_conversion",
            ],
            "copy_config": [
                "copy_source",
                "source_url",
                "copy_destination",
                "destination_url",
                "commit_conf",
                "xml_conversion",
            ],
            "rpc": ["xml_filter", "xml_conversion"],
        }
        list_parameters = list(set(sum(parameters.values(), [])))
        cls.groups = {
            "NETCONF Parameters": {
                "commands": ["nc_type"] + list_parameters,
                "default": "expanded",
            },
            **ConnectionForm.groups,
        }
        cls.input_data = HiddenField(
            "",
            default=dumps({
                "fields": list_parameters,
                "netconf_type": parameters
            }),
        )