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() look_for_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
class UnixShellScriptForm(NetmikoForm): form_type = HiddenField(default="unix_shell_script_service") enable_mode = BooleanField("Run as root using sudo") config_mode = BooleanField("Config mode") source_code = StringField( widget=TextArea(), render_kw={"rows": 15}, default=("#!/bin/bash\n" "# The following example shell script returns" " 0 for success; non-zero for failure\n" "directory_contents=`ls -al /root` # Needs privileged mode\n" "return_code=$?\n" "if [ $return_code -ne 0 ]; then\n" " exit $return_code # Indicating Failure\n" "else\n" ' echo -e "$directory_contents"\n' " exit 0 # Indicating Success\n" "fi\n"), ) driver = SelectField(choices=app.NETMIKO_DRIVERS, default="linux") use_device_driver = BooleanField(default=True) fast_cli = BooleanField() timeout = IntegerField(default=10) delay_factor = FloatField(default=1.0) global_delay_factor = FloatField(default=1.0) expect_string = StringField(substitution=True) auto_find_prompt = BooleanField(default=True) strip_prompt = BooleanField(default=True) strip_command = BooleanField(default=True) groups = { "Main Parameters": { "commands": ["source_code"], "default": "expanded" }, "Advanced Netmiko Parameters": { "commands": [ "expect_string", "auto_find_prompt", "strip_prompt", "strip_command", ], "default": "hidden", }, **NetmikoForm.groups, }
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() look_for_keys = BooleanField() source_file_includes_globbing = BooleanField( "Source file includes glob pattern (Put Direction only)") max_transfer_size = IntegerField(default=2**30) window_size = IntegerField(default=2**30) timeout = FloatField(default=10.0)
class NetmikoForm(ConnectionForm): form_type = HiddenField(default="netmiko") abstract_service = True driver = SelectField(choices=app.NETMIKO_DRIVERS) use_device_driver = BooleanField(default=True) enable_mode = BooleanField( "Enable mode (run in enable mode or as root)", default=True ) config_mode = BooleanField("Config mode", default=False) fast_cli = BooleanField() timeout = FloatField(default=10.0) delay_factor = FloatField( ( "Delay Factor (Changing from default of 1" " will nullify Netmiko Timeout setting)" ), default=1.0, ) global_delay_factor = FloatField( ( "Global Delay Factor (Changing from default of 1" " will nullify Netmiko Timeout setting)" ), default=1.0, ) jump_on_connect = BooleanField( "Jump to remote device on connect", default=False, render_kw={"help": "netmiko/jump_on_connect"}, ) jump_command = StringField( label="Command that jumps to device", default="ssh jump_server_IP", substitution=True, render_kw={"help": "netmiko/jump_command"}, ) jump_username = StringField( label="Device username", substitution=True, render_kw={"help": "netmiko/jump_username"}, ) jump_password = PasswordField( label="Device password", substitution=True, render_kw={"help": "netmiko/jump_password"}, ) exit_command = StringField( label="Command to exit device back to original device", default="exit", substitution=True, render_kw={"help": "netmiko/exit_command"}, ) expect_username_prompt = StringField( "Expected username prompt", default="username:"******"help": "netmiko/expect_username_prompt"}, ) expect_password_prompt = StringField( "Expected password prompt", default="password", substitution=True, render_kw={"help": "netmiko/expect_password_prompt"}, ) expect_prompt = StringField( "Expected prompt after login", default="admin.*$", substitution=True, render_kw={"help": "netmiko/expect_prompt"}, ) groups = { "Netmiko Parameters": { "commands": [ "driver", "use_device_driver", "enable_mode", "config_mode", "fast_cli", "timeout", "delay_factor", "global_delay_factor", ], "default": "expanded", }, **ConnectionForm.groups, "Jump on connect Parameters": { "commands": [ "jump_on_connect", "jump_command", "expect_username_prompt", "jump_username", "expect_password_prompt", "jump_password", "expect_prompt", "exit_command", ], "default": "hidden", }, }
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 field uses two validators: # - The input length must be comprised between 7 and 25 characters # - The input syntax must match that of an email address. mail_address = StringField( "Mail address", [Length(min=7, max=25), Email()]) # 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'")