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 NetmikoConfigurationForm(NetmikoForm): form_type = HiddenField(default="netmiko_configuration_service") config_mode = BooleanField("Config mode", default=True) content = StringField(widget=TextArea(), render_kw={"rows": 5}, substitution=True) commit_configuration = BooleanField() exit_config_mode = BooleanField(default=True) strip_prompt = BooleanField() strip_command = BooleanField() config_mode_command = StringField() groups = { "Main Parameters": { "commands": [ "content", "commit_configuration", "exit_config_mode", "config_mode_command", ], "default": "expanded", }, "Advanced Netmiko Parameters": { "commands": ["strip_prompt", "strip_command"], "default": "hidden", }, **NetmikoForm.groups, }
class NetmikoValidationForm(NetmikoForm): form_type = HiddenField(default="netmiko_validation_service") command = StringField(substitution=True) expect_string = StringField( substitution=True, render_kw={"help": "netmiko/expect_string"} ) auto_find_prompt = BooleanField( default=True, render_kw={"help": "netmiko/auto_find_prompt"} ) strip_prompt = BooleanField( default=True, render_kw={"help": "netmiko/strip_prompt"} ) strip_command = BooleanField( default=True, render_kw={"help": "netmiko/strip_command"} ) use_genie = BooleanField(default=False) groups = { "Main Parameters": {"commands": ["command"], "default": "expanded"}, **NetmikoForm.groups, "Advanced Netmiko Parameters": { "commands": [ "expect_string", "auto_find_prompt", "strip_prompt", "strip_command", "use_genie", ], "default": "hidden", }, }
class ConnectionForm(ServiceForm): form_type = HiddenField(default="connection") abstract_service = True 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) use_host_keys = BooleanField("Use Host Keys - Requires: 'Custom Credentials' with 'Custom Username'") start_new_connection = BooleanField("Start New Connection") close_connection = BooleanField("Close Connection") groups = { "Connection Parameters": { "commands": [ "credentials", "custom_username", "custom_password", "use_host_keys", "start_new_connection", "close_connection", ], "default": "expanded", } }
class NetmikoFileTransferForm(NetmikoForm): form_type = HiddenField(default="netmiko_file_transfer_service") source_file = StringField(validators=[InputRequired()], substitution=True) destination_file = StringField(validators=[InputRequired()], substitution=True) file_system = StringField() direction = SelectField(choices=(("put", "Upload"), ("get", "Download"))) disable_md5 = BooleanField() inline_transfer = BooleanField() overwrite_file = BooleanField() groups = { "Main Parameters": { "commands": [ "source_file", "destination_file", "file_system", "direction", "disable_md5", "inline_transfer", "overwrite_file", ], "default": "expanded", }, **NetmikoForm.groups, }
class GitForm(ServiceForm): form_type = HiddenField(default="git_service") git_repository = StringField("Path to Local Git Repository") relative_path = BooleanField("Path is relative to eNMS folder") pull = BooleanField("Git Pull") add_commit = BooleanField("Do 'git add' and commit") commit_message = StringField("Commit Message") push = BooleanField("Git Push")
class DatabaseMigrationsForm(BaseForm): template = "database_migration" form_type = HiddenField(default="database_migration") empty_database_before_import = BooleanField("Empty Database before Import") skip_update_pools_after_import = BooleanField( "Skip the Pool update after Import", default="checked") export_choices = [(p, p) for p in db.import_classes] import_export_types = SelectMultipleField("Instances to migrate", choices=export_choices)
class DatabaseMigrationsForm(BaseForm): template = "database_migration" form_type = HiddenField(default="database_migration") empty_database_before_import = BooleanField("Empty Database before Import") skip_pool_update = BooleanField("Skip the Pool update after Import", default="checked") export_private_properties = BooleanField("Include private properties", default="checked") export_choices = [(p, p) for p in app.database["import_export_models"]] import_export_types = SelectMultipleField("Instances to migrate", choices=export_choices)
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)
class RestartWorkflowForm(BaseForm): action = "eNMS.workflow.restartWorkflow" form_type = HiddenField(default="restart_workflow") start_services = MultipleInstanceField("Services", model="service") restart_runtime = SelectField("Restart Runtime", choices=(), validation=False) restart_from_top_level_workflow = BooleanField(default=True)
class UserForm(RbacForm): form_type = HiddenField(default="user") manual_rbac = BooleanField("Manually defined RBAC") theme = SelectField( "Theme", choices=[(theme, values["name"]) for theme, values in themes["themes"].items()], ) password = PasswordField("Password")
class ObjectForm(BaseForm): form_type = HiddenField(default="object") name = StringField("Name", [InputRequired()]) public = BooleanField("Public", default=False) description = StringField("Description") subtype = StringField("Subtype") location = StringField("Location") vendor = StringField("Vendor") model = StringField("Model")
class PoolForm(BaseForm): template = "pool" form_type = HiddenField(default="pool") id = HiddenField() name = StringField("Name", [InputRequired()]) public = BooleanField("Public", default=False) description = StringField("Description") longitude = StringField("Longitude", default=0.0) latitude = StringField("Latitude", default=0.0) operator = SelectField( "Type of match", choices=( ("all", "Match if all properties match"), ("any", "Match if any property matches"), ), ) manually_defined = BooleanField( "Manually defined (won't be automatically updated)")
class AnsiblePlaybookForm(ServiceForm): form_type = HiddenField(default="ansible_playbook_service") playbook_path = SelectField("Playbook Path", choices=(), validation=False) arguments = StringField("Arguments (Ansible command line options)", substitution=True) pass_device_properties = BooleanField( "Pass Device Inventory Properties (to be used " "in the playbook as {{name}} or {{ip_address}})") options = DictField("Options (passed to ansible as -e extra args)", substitution=True)
class ScrapliForm(ConnectionForm): form_type = HiddenField(default="scrapli_service") commands = StringField(substitution=True, widget=TextArea(), render_kw={"rows": 5}) is_configuration = BooleanField() driver = SelectField(choices=choices(app.SCRAPLI_DRIVERS)) transport = SelectField(choices=choices(("system", "paramiko", "ssh2"))) use_device_driver = BooleanField(default=True) groups = { "Main Parameters": { "commands": [ "commands", "is_configuration", "driver", "transport", "use_device_driver", ], "default": "expanded", }, **ConnectionForm.groups, }
class Form(BaseForm): form_type = HiddenField(default="custom") address = SelectField(choices=[("ipv4", "IPv4"), ("ipv6", "IPv6")]) connected_links = MultipleInstanceField("Links", model="link") hostname = StringField("Username", default="admin") ip_address = StringField("IP address") neighbor = InstanceField("Devices", model="device") ports = MultipleInstanceField("Port", model="port") password = PasswordField("Password") carry_customer_traffic = BooleanField("Carry Customer Traffic", default=False)
class PoolForm(BaseForm): template = "pool" form_type = HiddenField(default="pool") id = HiddenField() name = StringField("Name", [InputRequired()]) admin_only = BooleanField("Pool visible to admin users only") access_groups = StringField("Groups") description = StringField("Description") operator = SelectField( "Type of match", choices=( ("all", "Match if all properties match"), ("any", "Match if any property matches"), ), ) manually_defined = BooleanField( "Manually defined (won't be automatically updated)") @classmethod def form_init(cls): cls.models = ("device", "link", "service", "user") for model in cls.models: setattr(cls, f"{model}_properties", app.properties["filtering"][model]) for property in app.properties["filtering"][model]: setattr(cls, f"{model}_{property}", StringField(property)) setattr(cls, f"{model}_{property}_invert", BooleanField(property)) form_properties["pool"][f"{model}_{property}_invert"] = { "type": "bool" } setattr( cls, f"{model}_{property}_match", SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), )), )
class UserForm(RbacForm): form_type = HiddenField(default="user") is_admin = BooleanField(default=False) authentication = SelectField( "Authentication Method", choices=[(method, values["display_name"]) for method, values in settings["authentication"]["methods"].items()], ) theme = SelectField( "Theme", choices=[(theme, values["name"]) for theme, values in themes["themes"].items()], ) password = PasswordField("Password")
class NapalmForm(ConnectionForm): form_type = HiddenField(default="napalm") abstract_service = True driver = SelectField(choices=app.NAPALM_DRIVERS) use_device_driver = BooleanField(default=True) timeout = IntegerField(default=10) optional_args = DictField() groups = { "Napalm Parameters": { "commands": ["driver", "use_device_driver", "timeout", "optional_args"], "default": "expanded", }, **ConnectionForm.groups, }
class RestCallForm(ServiceForm): form_type = HiddenField(default="rest_call_service") call_type = SelectField(choices=( ("GET", "GET"), ("POST", "POST"), ("PUT", "PUT"), ("DELETE", "DELETE"), ("PATCH", "PATCH"), )) rest_url = StringField(substitution=True) payload = DictField(json_only=True, substitution=True) params = DictField(substitution=True) headers = DictField(substitution=True) verify_ssl_certificate = BooleanField("Verify SSL Certificate") timeout = IntegerField(default=15) username = StringField() password = PasswordField()
class WorkflowForm(ServiceForm): form_type = HiddenField(default="workflow") close_connection = BooleanField(default=False) run_method = SelectField( "Run Method", choices=( ("per_device", "Run the workflow device by device"), ( "per_service_with_workflow_targets", "Run the workflow service by service using workflow targets", ), ( "per_service_with_service_targets", "Run the workflow service by service using service targets", ), ), ) superworkflow = InstanceField("Superworkflow")
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, }
def form_init(cls): cls.models = ("device", "link", "service", "user") for model in cls.models: setattr(cls, f"{model}_properties", app.properties["filtering"][model]) for property in app.properties["filtering"][model]: setattr(cls, f"{model}_{property}", StringField(property)) setattr(cls, f"{model}_{property}_invert", BooleanField(property)) form_properties["pool"][f"{model}_{property}_invert"] = {"type": "bool"} setattr( cls, f"{model}_{property}_match", SelectField( choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), ) ), )
class DataBackupForm(NetmikoForm): form_type = HiddenField(default="netmiko_backup_service") property = SelectField( "Configuration Property to Update", choices=list(app.configuration_properties.items()), ) commands = FieldList(FormField(CommandsForm), min_entries=12) replacements = FieldList(FormField(ReplacementForm), min_entries=12) add_header = BooleanField("Add header for each ommand", default=True) groups = { "Target property and commands": { "commands": ["property", "add_header", "commands"], "default": "expanded", }, "Search Response & Replace": { "commands": ["replacements"], "default": "expanded", }, **NetmikoForm.groups, }
def configure_form(cls): cls.properties = ("log_source", "log_content") for property in ("log_source", "log_content"): setattr(cls, property, StringField(property)) setattr(cls, property + "_regex", BooleanField("Regex")) return cls
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 }), )
class ExcelImportForm(BaseForm): template = "topology_import" form_type = HiddenField(default="excel_import") replace = BooleanField("Replace Existing Topology")
class SettingsForm(BaseForm): form_type = HiddenField(default="settings_panel") action = "eNMS.administration.saveSettings" settings = JsonField("Settings") write_changes = BooleanField("Write changes back to 'settings.json' file")
class ServiceForm(BaseForm): template = "service" form_type = HiddenField(default="service") id = HiddenField() name = StringField("Name") type = StringField("Service Type") shared = BooleanField("Shared Service") 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")) ) devices = MultipleInstanceField("Devices") disable_result_creation = BooleanField("Disable Result Creation") pools = MultipleInstanceField("Pools") update_pools = BooleanField("Update pools before running") workflows = MultipleInstanceField("Workflows") waiting_time = IntegerField( "Time to Wait before next service is started (in seconds)", default=0 ) 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}) 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) maximum_runs = IntegerField("Maximum number of runs", default=1) skip = BooleanField("Skip") skip_query = StringField( "Skip Query (Python)", python=True, widget=TextArea(), render_kw={"rows": 2} ) skip_value = SelectField( "Skip Value", choices=(("True", "True"), ("False", "False")), ) vendor = StringField("Vendor") operating_system = StringField("Operating System") iteration_values = StringField("Iteration Values", python=True) initial_payload = DictField() 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=( ("always", "Always run"), ("success", "Run on success only"), ("failure", "Run on failure only"), ) ) public = BooleanField("Public") log_level = SelectField( "Logging", choices=((0, "Disable logging"), *enumerate(app.log_levels, 1)), default=1, validation=False, ) multiprocessing = BooleanField("Multiprocessing") max_processes = IntegerField("Maximum number of processes", default=15) validation_condition = SelectField( choices=( ("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=( ("none", "No validation"), ("text", "Validation by text match"), ("dict_included", "Validation by dictionary inclusion"), ("dict_equal", "Validation by dictionary equality"), ), ) content_match = StringField( "Content Match", widget=TextArea(), render_kw={"rows": 8}, substitution=True ) content_match_regex = BooleanField("Match content with 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.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." ) return ( valid_form and not no_recipient_error and not conversion_validation_mismatch and not forbidden_name_error )
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", }, }