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
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(help="netmiko/config_mode_command") groups = { "Main Parameters": { "commands": [ "content", "commit_configuration", "exit_config_mode", "config_mode_command", ], "default": "expanded", }, **NetmikoForm.groups, "Advanced Netmiko Parameters": { "commands": ["strip_prompt", "strip_command"], "default": "hidden", }, }
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")
class SlackNotificationForm(ServiceForm): form_type = HiddenField(default="slack_notification_service") channel = StringField(substitution=True) token = StringField() body = StringField(widget=TextArea(), render_kw={"rows": 5}, substitution=True)
class NetmikoValidationForm(NetmikoForm): form_type = HiddenField(default="netmiko_validation_service") command = StringField(substitution=True) use_textfsm = BooleanField("Use TextFSM", default=False) expect_string = StringField(substitution=True, help="netmiko/expect_string") config_mode_command = StringField(help="netmiko/config_mode_command") auto_find_prompt = BooleanField(default=True, help="netmiko/auto_find_prompt") strip_prompt = BooleanField(default=True, help="netmiko/strip_prompt") strip_command = BooleanField(default=True, help="netmiko/strip_command") groups = { "Main Parameters": { "commands": ["command"], "default": "expanded" }, **NetmikoForm.groups, "Advanced Netmiko Parameters": { "commands": [ "use_textfsm", "expect_string", "config_mode_command", "auto_find_prompt", "strip_prompt", "strip_command", ], "default": "hidden", }, }
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 ConnectionForm(ServiceForm): form_type = HiddenField(default="connection") get_request_allowed = False 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) start_new_connection = BooleanField("Start New Connection") connection_name = StringField("Connection Name", default="default") close_connection = BooleanField("Close Connection") groups = { "Connection Parameters": { "commands": [ "credentials", "custom_username", "custom_password", "start_new_connection", "connection_name", "close_connection", ], "default": "expanded", } }
class RbacForm(BaseForm): action = "eNMS.base.processData" form_type = HiddenField(default="rbac") get_request_allowed = False id = HiddenField() name = StringField("Name", [InputRequired()]) description = StringField(widget=TextArea(), render_kw={"rows": 6}) email = StringField("Email")
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 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)
class DebugForm(BaseForm): template = "debug" form_type = HiddenField(default="debug") snippets = SelectField(validate_choice=False) code = StringField( "Python Code", type="code", python=True, widget=TextArea(), render_kw={"rows": 15}, ) output = StringField("Output", widget=TextArea(), render_kw={"rows": 16})
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])
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, }
def form_init(cls): cls.models = ("device", "link", "service", "user") for model in cls.models: setattr(cls, f"{model}_properties", vs.properties["filtering"][model]) for property in vs.properties["filtering"][model]: setattr(cls, f"{model}_{property}", StringField(property)) setattr(cls, f"{model}_{property}_invert", BooleanField(property)) vs.form_properties["pool"][f"{model}_{property}_match"] = { "type": "list" } vs.form_properties["pool"][f"{model}_{property}_invert"] = { "type": "bool" } setattr( cls, f"{model}_{property}_match", SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), ("empty", "Empty"), )), )
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 ResultLogDeletionForm(BaseForm): action = "eNMS.administration.resultLogDeletion" form_type = HiddenField(default="result_log_deletion") deletion_types = SelectMultipleField( "Instances do delete", choices=[("run", "result"), ("changelog", "changelog")], ) date_time = StringField(type="date", label="Delete Records before")
class WorkflowLabelForm(BaseForm): form_type = HiddenField(default="workflow_label") action = "eNMS.workflowBuilder.createLabel" text = StringField(widget=TextArea(), render_kw={"rows": 15}) alignment = SelectField( "Text Alignment", choices=(("left", "Left"), ("center", "Center"), ("right", "Right")), )
class NetmikoPromptsForm(NetmikoForm): form_type = HiddenField(default="netmiko_prompts_service") command = StringField(substitution=True) confirmation1 = StringField(substitution=True, help="netmiko/confirmation") response1 = StringField(substitution=True, help="netmiko/confirmation") confirmation2 = StringField(substitution=True, help="netmiko/confirmation") response2 = StringField(substitution=True, help="netmiko/confirmation") confirmation3 = StringField(substitution=True, help="netmiko/confirmation") response3 = StringField(substitution=True, help="netmiko/confirmation") groups = { "Main Parameters": { "commands": [ "command", "confirmation1", "response1", "confirmation2", "response2", "confirmation3", "response3", ], "default": "expanded", }, **NetmikoForm.groups, }
class DataExtractionForm(ServiceForm): form_type = HiddenField(default="data_extraction_service") variable1 = StringField("Variable Name") query1 = StringField("Python Extraction Query", python=True) match_type1 = SelectField("Post Processing", choices=match_choices) match1 = StringField( "Regular Expression / TextFSM Template Text", widget=TextArea(), render_kw={"rows": 5}, ) operation1 = SelectField("Operation", choices=operation_choices) variable2 = StringField("Variable Name") query2 = StringField("Python Extraction Query", python=True) match_type2 = SelectField("Post Processing", choices=match_choices) match2 = StringField( "Regular Expression / TextFSM Template Text", widget=TextArea(), render_kw={"rows": 5}, ) operation2 = SelectField("Operation", choices=operation_choices) variable3 = StringField("Variable Name") query3 = StringField("Python Extraction Query", python=True) match_type3 = SelectField("Post Processing", choices=match_choices) match3 = StringField( "Regular Expression / TextFSM Template Text", widget=TextArea(), render_kw={"rows": 5}, ) operation3 = SelectField("Operation", choices=operation_choices) groups = { "Extraction 1": { "commands": ["variable1", "query1", "match_type1", "match1", "operation1"], "default": "expanded", }, "Extraction 2": { "commands": ["variable2", "query2", "match_type2", "match2", "operation2"], "default": "expanded", }, "Extraction 3": { "commands": ["variable3", "query3", "match_type3", "match3", "operation3"], "default": "expanded", }, }
class MailNotificationForm(ServiceForm): form_type = HiddenField(default="mail_notification_service") title = StringField(substitution=True) sender = StringField() recipients = StringField() replier = StringField("Reply-to Address") body = StringField(widget=TextArea(), render_kw={"rows": 5}, substitution=True) def validate(self): valid_form = super().validate() for field in ("title", "sender", "recipients", "body"): if not getattr(self, field).data: getattr( self, field).errors.append(f"{field.capitalize()} is missing.") valid_form = False return valid_form
class AddServiceForm(BaseForm): form_type = HiddenField(default="add_services_to_workflow") template = "add_services_to_workflow" mode = SelectField( "Mode", choices=( ("deep", "Deep Copy (creates a duplicate from the service)"), ("shallow", "Shallow Copy (creates a reference to the service)"), ), ) search = StringField()
class DeviceConnectionForm(BaseForm): template = "device_connection" form_type = HiddenField(default="device_connection") address_choices = [("ip_address", "IP address"), ("name", "Name")] + [ (property, values["pretty_name"]) for property, values in vs.properties["custom"]["device"].items() if values.get("is_address", False) ] address = SelectField(choices=address_choices) username = StringField("Username") password = PasswordField("Password")
class LoginForm(BaseForm): form_type = HiddenField(default="login") get_request_allowed = False authentication_method = SelectField( "Authentication Method", choices=[(method, properties["display_name"]) for method, properties in vs.settings["authentication"]["methods"].items() if properties["enabled"]], ) username = StringField("Name", [InputRequired()]) password = PasswordField("Password", [InputRequired()])
def generate_filtering_forms(self): for model, properties in vs.properties["filtering"].items(): relations = {} for related_model, relation in vs.relationships[model].items(): if related_model in ("edges", "results"): continue relations[related_model] = MultipleInstanceField( related_model, model=related_model) vs.relationships[f"{model}_filtering"][ related_model] = relation filtering_key = f"{model}_relation_filtering" vs.relationships[filtering_key][related_model] = relation relation_form = { "template": "filtering", "properties": sorted(relations), "object_type": model, "form_type": HiddenField(default=f"{model}_relation_filtering"), **{ **relations, **{ f"{relation}_filter": SelectField(choices=( ("union", "Union"), ("intersection", "Intersection"), ("empty", "Empty"), )) for relation in relations }, }, } type(f"{model}RelationshipFilteringForm", (BaseForm, ), relation_form) form, form_type = deepcopy(relation_form), f"{model}_filtering" for property in properties: vs.form_properties[form_type][f"{property}_filter"] = { "type": "list" } form.update({ "form_type": HiddenField(default=form_type), "properties": sorted(properties) + sorted(relations), **{property: StringField() for property in properties}, **{ f"{property}_filter": SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), ("empty", "Empty"), )) for property in properties }, }) type(f"{model}FilteringForm", (BaseForm, ), form)
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, }
class TopologyImportForm(ServiceForm): form_type = HiddenField(default="topology_import_service") import_type = SelectField(choices=( ("librenms", "LibreNMS"), ("netbox", "Netbox"), ("opennms", "OpenNMS"), )) netbox_address = StringField(default="http://0.0.0.0:8000") netbox_token = PasswordField() opennms_address = StringField() opennms_devices = StringField() opennms_login = StringField() opennms_password = PasswordField() librenms_address = StringField(default="http://librenms.example.com") librenms_token = PasswordField() groups = { "Type of Import": { "commands": ["import_type"], "default": "expanded" }, "Netbox": { "commands": ["netbox_address", "netbox_token"], "default": "expanded", }, "OpenNMS": { "commands": [ "opennms_address", "opennms_devices", "opennms_login", "opennms_password", ], "default": "expanded", }, "LibreNMS": { "commands": ["librenms_address", "librenms_token"], "default": "expanded", }, }
class NapalmConfigurationForm(NapalmForm): form_type = HiddenField(default="napalm_configuration_service") action = SelectField( choices=( ("load_merge_candidate", "Load merge"), ("load_replace_candidate", "Load replace"), ) ) content = StringField(widget=TextArea(), render_kw={"rows": 5}, substitution=True) groups = { "Main Parameters": {"commands": ["action", "content"], "default": "expanded"}, **NapalmForm.groups, }
class ObjectForm(BaseForm): action = "eNMS.base.processData" form_type = HiddenField(default="object") get_request_allowed = False id = HiddenField() name = StringField("Name", [InputRequired()]) access_groups = StringField("Groups") description = StringField("Description") subtype = StringField("Subtype") location = StringField("Location") vendor = StringField("Vendor") model = StringField("Model")
class PythonSnippetForm(ServiceForm): form_type = HiddenField(default="python_snippet_service") source_code = StringField( type="code", python=True, widget=TextArea(), render_kw={"rows": 15, "help": "python_snippet/source_code"}, default=""" # Click on "i" to right of "Source Code" for examples. result = {} results["success"] = True results["result"] = result""", )
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") 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", vs.properties["filtering"][model]) for property in vs.properties["filtering"][model]: setattr(cls, f"{model}_{property}", StringField(property)) setattr(cls, f"{model}_{property}_invert", BooleanField(property)) vs.form_properties["pool"][f"{model}_{property}_match"] = { "type": "list" } vs.form_properties["pool"][f"{model}_{property}_invert"] = { "type": "bool" } setattr( cls, f"{model}_{property}_match", SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), ("empty", "Empty"), )), )