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 RunServiceForm(BaseForm): action = "eNMS.automation.runServicesOnTargets" button_label = "Run Service" button_class = "primary" form_type = HiddenField(default="run_service") targets = HiddenField() type = HiddenField() service = InstanceField("Services", model="service")
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 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")
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 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 NodeForm(BaseForm): action = "eNMS.base.processData" form_type = HiddenField(default="node") id = HiddenField() name = StringField("Name", [InputRequired()]) device = InstanceField("Device", model="device") position_x = FloatField("Position (X)", default=0.0) position_y = FloatField("Position (Y)", default=0.0) position_z = FloatField("Position (Z)", default=0.0) scale_x = FloatField("Scale (X)", default=1.0) scale_y = FloatField("Scale (Y)", default=1.0) scale_z = FloatField("Scale (Z)", default=1.0) rotation_x = FloatField("Rotation (X)", default=0.0) rotation_y = FloatField("Rotation (Y)", default=0.0) rotation_z = FloatField("Rotation (Z)", default=0.0)
class ChangelogForm(BaseForm): action = "eNMS.base.processData" form_type = HiddenField(default="changelog") id = HiddenField() severity = SelectField( "Severity", choices=( ("debug", "Debug"), ("info", "Info"), ("warning", "Warning"), ("error", "Error"), ("critical", "Critical"), ), ) content = StringField(widget=TextArea(), render_kw={"rows": 10})
class RestartWorkflowForm(BaseForm): action = "eNMS.workflowBuilder.restartWorkflow" form_type = HiddenField(default="restart_workflow") start_services = HiddenField() restart_runtime = SelectField("Restart Runtime", validate_choice=False) targets = SelectField( "Targets", choices=( ("Manually defined", "Use the devices manually defined below."), ("Restart run", "Use the targets from the restart run."), ("Workflow", "Use the targets defined at workflow level."), ), ) restart_devices = MultipleInstanceField("Devices", model="device") restart_pools = MultipleInstanceField("Pools", model="pool")
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 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 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 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 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 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 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 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 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 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 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 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 NapalmGettersForm(NapalmForm): form_type = HiddenField(default="napalm_getters_service") getters = SelectMultipleField(choices=vs.automation["napalm"]["getters"]) groups = { "Main Parameters": { "commands": ["getters"], "default": "expanded" }, **NapalmForm.groups, }
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 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 = vs.dualize(db.import_export_models) import_export_types = SelectMultipleField("Instances to migrate", choices=export_choices)
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()])
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 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 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, }
def generate_instance_insertion_forms(self): for model in ("device", "link", "user", "service"): vs.relationships[f"add_{model}s"]["instances"] = { "type": "object-list", "model": model, } type( f"{model}RelationshipFilteringForm", (BaseForm, ), { "form_type": HiddenField(default=f"add_{model}s"), "action": "eNMS.base.addInstancesToRelation", "model": HiddenField(default=model), "relation_id": HiddenField(), "relation_type": HiddenField(), "property": HiddenField(), "instances": MultipleInstanceField(f"{model}s", model=model), "names": StringField(widget=TextArea(), render_kw={"rows": 8}), }, )
class AccessForm(RbacForm): template = "access" form_type = HiddenField(default="access") user_pools = MultipleInstanceField("pool", model="pool") access_pools = MultipleInstanceField("pool", model="pool") access_type = SelectMultipleStringField( "Access Type", choices=vs.dualize([ "Read", "Edit", "Run", "Schedule", "Connect", "Use as target" ]), ) relations = ["pools", "services"] @classmethod def form_init(cls): keys = ( "get_requests", "post_requests", "delete_requests", "upper_menu", ) for key in keys: values = [(k, k) for k, v in vs.rbac[key].items() if v == "access"] field_name = " ".join(key.split("_")).capitalize() setattr(cls, key, SelectMultipleField(field_name, choices=values)) menus, pages = [], [] for category, values in vs.rbac["menu"].items(): if values["rbac"] == "admin": continue if values["rbac"] == "access": menus.append(category) for page, page_values in values["pages"].items(): if page_values["rbac"] == "admin": continue if page_values["rbac"] == "access": pages.append(page) subpages = page_values.get("subpages", {}) for subpage, subpage_values in subpages.items(): if subpage_values["rbac"] == "admin": continue if subpage_values["rbac"] == "access": pages.append(subpage) menu_choices = vs.dualize(menus) setattr(cls, "menu", SelectMultipleField("Menu", choices=menu_choices)) page_choices = vs.dualize(pages) setattr(cls, "pages", SelectMultipleField("Pages", choices=page_choices))