class PoolObjectsForm(BaseForm): template = "pool_objects" form_type = HiddenField(default="pool_objects") devices = MultipleInstanceField("Devices") links = MultipleInstanceField("Links") string_devices = StringField(widget=TextArea(), render_kw={"rows": 5}) string_links = StringField(widget=TextArea(), render_kw={"rows": 5})
class TaskForm(BaseForm): template = "object" form_type = HiddenField(default="task") id = HiddenField() is_active = BooleanField("Is Active") name = StringField("Name") description = StringField("Description") start_date = DateField("Start Date") end_date = DateField("End 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") job = InstanceField("Job", instance_type="Job") scheduling_mode = SelectField( "Scheduling Mode", choices=(("standard", "Standard Scheduling"), ("cron", "Crontab Scheduling")), ) devices = MultipleInstanceField("Devices", instance_type="Device") pools = MultipleInstanceField("Pools", instance_type="Pool") payload = DictField("Payload")
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 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)
def filtering_form_generator(): for form_type, properties in model_properties.items(): relations = {} for model, relation in relationships[form_type].items(): if model in ("edges", "results"): continue relations[model] = MultipleInstanceField(model) relationships[f"{form_type}_filtering"][model] = relation type( f"{form_type.capitalize()}FilteringForm", (BaseForm, ), { "template": "filtering", "properties": sorted(relations), "form_type": HiddenField(default=f"{form_type}_filtering"), **{ **relations, **{ f"{relation}_filter": SelectField(choices=( ("any", "Any"), ("not_any", "Unrelated"), ("none", "None"), )) for relation in relations }, }, }, )
class RestartWorkflowForm(BaseForm): action = "restartWorkflow" form_type = HiddenField(default="restart_workflow") start_jobs = MultipleInstanceField("Workflow Entry Point(s)", instance_type="Job") restart_runtime = NoValidationSelectField("Restart Runtime", choices=()) payloads_to_exclude = NoValidationSelectMultipleField( "Payloads to Exclude", choices=())
def filtering_form_generator() -> None: for table, properties in filtering_properties.items(): kwargs = {} if table in ("device", "link", "configuration"): kwargs["pools"] = MultipleInstanceField("Pools", instance_type="Pool") if table == "service": kwargs["workflows"] = MultipleInstanceField( "Workflows", instance_type="Workflow") if table == "workflow": kwargs["services"] = MultipleInstanceField("Services", instance_type="Service") type( f"{table.capitalize()}FilteringForm", (BaseForm, ), { "template": "filtering", "properties": list(kwargs) + properties, "form_type": HiddenField(default=f"{table}_filtering"), "operator": SelectField( "Match Condition", choices=( ("all", "Match if all properties match"), ("any", "Match if any property matches"), ), ), **{ **{property: StringField() for property in properties}, **{ f"{property}_filter": SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), )) for property in properties }, **kwargs, }, }, )
class AccessForm(RbacForm): template = "access" form_type = HiddenField(default="access") user_pools = MultipleInstanceField("pool") access_pools = MultipleInstanceField("pool") access_type = SelectMultipleStringField( "Access Type", choices=choices( ["Read", "Edit", "Run", "Schedule", "Connect", "Use as target"]), ) relations = ["pools", "services"] @classmethod def form_init(cls): cls.configure_relationships("users") keys = ("get_requests", "post_requests", "delete_requests", "upper_menu") for key in keys: values = [(k, k) for k, v in app.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 app.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) setattr(cls, "menu", SelectMultipleField("Menu", choices=choices(menus))) setattr(cls, "pages", SelectMultipleField("Pages", choices=choices(pages)))
def configure_access_form(cls): cls.models = app.rbac["models"] for model, access_rights in cls.models.items(): setattr(cls, model, MultipleInstanceField()) form_properties["access"][model] = {"type": "object-list"} access_field = SelectMultipleStringField( choices=choices(access_rights)) form_properties["access"][f"{model}_access"] = { "type": "multiselect-string" } setattr(cls, f"{model}_access", access_field) return cls
class WorkflowForm(JobForm): form_type = HiddenField(default="workflow") use_workflow_devices = BooleanField("Use Workflow Devices", default=True) traversal_mode = SelectField( "Traversal Mode", choices=( ("service", "Workflow runs one service at a time"), ("device", "All devices run independently through the workflow"), ), ) start_jobs = MultipleInstanceField("Workflow Entry Point(s)", instance_type="Job") restart_runtime = NoValidationSelectField("Restart Runtime", choices=())
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": 13}) role = SelectField( "Role", choices=( ("read-write", "Read Write"), ("read-only", "Read Only"), ), ) subtype = SelectField("Type", 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") enable_password = PasswordField("'Enable' Password") password = PasswordField("Password") private_key = StringField(widget=TextArea(), render_kw={"rows": 10})
def filtering_form_generator(): for table, properties in filtering_properties.items(): relations = {} for model, relation in relationships[table].items(): if model in ("edges", "results"): continue relations[model] = MultipleInstanceField(model) relationships[f"{table}_filtering"][model] = relation type( f"{table.capitalize()}FilteringForm", (BaseForm, ), { "template": "filtering", "properties": list(relations) + properties, "form_type": HiddenField(default=f"{table}_filtering"), "operator": SelectField( "Type of match", choices=( ("all", "Match if all properties match"), ("any", "Match if any property matches"), ), ), **{ **{property: StringField() for property in properties}, **{ f"{property}_filter": SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), )) for property in properties }, **relations, **{ f"{relation}_filter": SelectField(choices=( ("any", "Any"), ("not_any", "Not related to Any"), ("none", "None"), )) for relation in relations }, }, }, )
class UserForm(BaseForm): template = "object" form_type = HiddenField(default="user") id = HiddenField() name = StringField("Name") password = PasswordField("Password") email = StringField("Email") permission_choices = [ ("Admin", "Admin"), ("Connect to device", "Connect to device"), ("View", "View"), ("Edit", "Edit"), ] permissions = SelectMultipleField("Permissions", choices=permission_choices) pools = MultipleInstanceField("Pools", instance_type="Pool")
class WorkflowForm(JobForm): form_type = HiddenField(default="workflow") device_targets_mode = SelectField( "Device Targets Mode", choices=( ("service", "Run with Workflow Targets, service by service"), ("device", "Run with Workflow Targets, device by device"), ("ignore", "Run with Service Targets"), ), ) start_jobs = MultipleInstanceField("Workflow Entry Point(s)", instance_type="Job") restart_runtime = NoValidationSelectField("Restart Runtime", choices=()) payloads_to_exclude = NoValidationSelectMultipleField( "Payloads to Exclude", choices=())
def filtering_form_generator(): for form_type in models: properties, relations = app.properties["filtering"].get(form_type, []), {} for model, relation in relationships[form_type].items(): if model in ("edges", "results"): continue relations[model] = MultipleInstanceField(model) relationships[f"{form_type}_filtering"][model] = relation relationships[f"{form_type}_relation_filtering"][model] = relation relation_form = { "template": "filtering", "properties": sorted(relations), "object_type": form_type, "form_type": HiddenField(default=f"{form_type}_relation_filtering"), **{ **relations, **{ f"{relation}_filter": SelectField(choices=( ("any", "Any"), ("all", "All"), ("not_any", "Unrelated"), ("none", "None"), )) for relation in relations }, }, } type(f"{form_type}RelationshipFilteringForm", (BaseForm, ), relation_form) form = deepcopy(relation_form) form.update({ "form_type": HiddenField(default=f"{form_type}_filtering"), "properties": sorted(properties) + sorted(relations), **{property: StringField() for property in properties}, **{ f"{property}_filter": SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), )) for property in properties }, }) type(f"{form_type}FilteringForm", (BaseForm, ), form)
def filtering_form_generator() -> None: for table, properties in filtering_properties.items(): table_model = table.capitalize( ) if table != "configuration" else "Device" relations = { model: MultipleInstanceField(model.capitalize(), instance_type=relation["model"]) for model, relation in relationships[table_model].items() if model not in ("edges", "results") } type( f"{table.capitalize()}FilteringForm", (BaseForm, ), { "template": "filtering", "properties": list(relations) + properties, "form_type": HiddenField(default=f"{table}_filtering"), "operator": SelectField( "Match Condition", choices=( ("all", "Match if all properties match"), ("any", "Match if any property matches"), ), ), **{ **{property: StringField() for property in properties}, **{ f"{property}_filter": SelectField(choices=( ("inclusion", "Inclusion"), ("equality", "Equality"), ("regex", "Regular Expression"), )) for property in properties }, **relations, **{ f"{relation}_filter": SelectField(choices=(("any", "Any"), ("not_any", "Not related to Any"))) for relation in relations }, }, }, )
def add_instance_form_generator(): for model in ("device", "link", "user", "service"): 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 EventForm(BaseForm): template = "event" form_type = HiddenField(default="event") id = HiddenField() name = StringField("Name") services = MultipleInstanceField("Services")
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") device_query_property = SelectField("Query Property Type", choices=(("name", "Name"), ("ip_address", "IP address"))) devices = MultipleInstanceField("Devices") pools = MultipleInstanceField("Pools") workflows = MultipleInstanceField("Workflows") waiting_time = IntegerField("Waiting time (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)") number_of_retries = IntegerField("Number of retries", default=0) time_between_retries = IntegerField("Time between retries (in seconds)", default=10) maximum_runs = IntegerField("Maximum number of runs", default=1) skip = BooleanField("Skip") skip_query = StringField("Skip Query (Python)") vendor = StringField("Vendor") operating_system = StringField("Operating System") initial_payload = DictField() iteration_values = StringField("Iteration Values (Python Query)") iteration_variable_name = StringField("Iteration Variable Name", default="iteration_value") iteration_devices = StringField("Iteration Devices (Python Query)") iteration_devices_property = SelectField( "Iteration Devices Property", choices=(("name", "Name"), ("ip_address", "IP address")), ) result_postprocessing = StringField(widget=TextArea(), render_kw={"rows": 7}) multiprocessing = BooleanField("Multiprocessing") max_processes = IntegerField("Maximum number of processes", default=50) 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 = SubstitutionField("Content Match", widget=TextArea(), render_kw={"rows": 8}) content_match_regex = BooleanField("Match content with Regular Expression") dict_match = DictSubstitutionField("Dictionary to Match Against") negative_logic = BooleanField("Negative logic") delete_spaces_before_matching = BooleanField( "Delete Spaces before Matching") query_fields = [ "device_query", "skip_query", "iteration_values", "result_postprocessing", ] 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 and not app.config["mail"]["recipients"]) if no_recipient_error: self.mail_recipient.errors.append( "Please add at least one recipient for the mail notification.") bracket_error = False for query_field in self.query_fields: field = getattr(self, query_field) try: parse(field.data) except Exception as exc: bracket_error = True field.errors.append(f"Wrong python expression ({exc}).") if "{{" in field.data and "}}" in field.data: bracket_error = True field.errors.append( "You cannot use variable substitution " "in a field expecting a python expression.") 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 bracket_error and not conversion_validation_mismatch)
class JobForm(BaseForm): template = "job" form_type = HiddenField(default="job") id = HiddenField() type = StringField("Service Type") name = StringField("Name") description = StringField("Description") python_query = StringField("Python Query") query_property_type = SelectField("Query Property Type", choices=(("name", "Name"), ("ip_address", "IP address"))) devices = MultipleInstanceField("Devices", instance_type="Device") pools = MultipleInstanceField("Pools", instance_type="Pool") waiting_time = IntegerField("Waiting time (in seconds)", default=0) send_notification = BooleanField("Send a notification") send_notification_method = SelectField( "Notification Method", choices=( ("mail_feedback_notification", "Mail"), ("slack_feedback_notification", "Slack"), ("mattermost_feedback_notification", "Mattermost"), ), ) notification_header = StringField(widget=TextArea(), render_kw={"rows": 5}) 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)") number_of_retries = IntegerField("Number of retries", default=0) time_between_retries = IntegerField("Time between retries (in seconds)", default=10) start_new_connection = BooleanField("Start New Connection") skip = BooleanField("Skip") skip_python_query = StringField("Skip (Python Query)") vendor = StringField("Vendor") operating_system = StringField("Operating System") shape = SelectField( "Shape", choices=( ("box", "Box"), ("circle", "Circle"), ("square", "Square"), ("diamond", "Diamond"), ("triangle", "Triangle"), ("ellipse", "Ellipse"), ("database", "Database"), ), ) size = IntegerField("Size", default=40) color = StringField("Color", default="#D2E5FF") initial_payload = DictField() iteration_targets = StringField("Iteration Targets (Python Query)") query_fields = ["python_query", "skip_python_query", "iteration_targets"] def validate(self) -> bool: valid_form = super().validate() no_recipient_error = (self.send_notification.data and self.send_notification_method.data == "mail_feedback_notification" and not self.mail_recipient.data and not controller.mail_recipients) bracket_error = False for query_field in self.query_fields: field = getattr(self, query_field) try: parse(field.data) except Exception as exc: bracket_error = True field.errors.append(f"Wrong python expression ({exc}).") if "{{" in field.data and "}}" in field.data: bracket_error = True field.errors.append( "You cannot use variable substitution " "in a field expecting a python expression.") if no_recipient_error: self.mail_recipient.errors.append( "Please add at least one recipient for the mail notification.") return valid_form and not no_recipient_error and not bracket_error
class AddJobsForm(BaseForm): action = "addJobsToWorkflow" form_type = HiddenField(default="add_jobs") jobs = MultipleInstanceField("Add jobs", instance_type="Job")
class WorkflowForm(ServiceForm): form_type = HiddenField(default="workflow") close_connection = BooleanField(default=False) start_services = MultipleInstanceField("Workflow Entry Point(s)") restart_runtime = NoValidationSelectField("Restart Runtime", choices=())
class EventForm(BaseForm): template = "event" form_type = HiddenField(default="event") id = HiddenField() name = StringField("Name") jobs = MultipleInstanceField("Jobs", instance_type="Job")
class RestartWorkflowForm(BaseForm): action = "restartWorkflow" form_type = HiddenField(default="restart_workflow") start_services = MultipleInstanceField("Workflow Entry Point(s)") restart_runtime = NoValidationSelectField("Restart Runtime", choices=())
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 AddServicesForm(BaseForm): action = "addServicesToWorkflow" form_type = HiddenField(default="add_services") services = MultipleInstanceField("Add services")
class RestartWorkflowForm(BaseForm): action = "eNMS.workflow.restartWorkflow" form_type = HiddenField(default="restart_workflow") start_services = MultipleInstanceField("Services", model="service") restart_runtime = NoValidationSelectField("Restart Runtime", choices=()) restart_from_top_level_workflow = BooleanField(default=True)
class VisualizationForm(BaseForm): action = "eNMS.visualization.saveParameters" form_type = HiddenField(default="visualization_parameters") default_pools = MultipleInstanceField("Pools", model="pool")