Exemple #1
0
class ReportWidget(Updateable):
    form = Form(fields=[
        ("title", "//input[@id='title']"),
        ("description", "//input[@id='description']"),
        ("active", "//input[@id='enabled']"),
        ("filter", ShowingInputs(
            Select("//select[@id='filter_typ']"),
            Select("//select[@id='subfilter_typ']"),
            Select("//select[@id='repfilter_typ']"),
            min_values=3
        )),  # Might be abstracted out too
        ("columns", ShowingInputs(
            Select("//select[@id='chosen_pivot1']"),
            Select("//select[@id='chosen_pivot2']"),
            Select("//select[@id='chosen_pivot3']"),
            Select("//select[@id='chosen_pivot4']"),
            min_values=1
        )),
        ("rows", Select("//select[@id='row_count']")),
        ("timer", Timer()),
        ("visibility", visibility_obj),
    ])

    def __init__(self,
            title, description=None, active=None, filter=None, columns=None, rows=None, timer=None,
            visibility=None):
        self.title = title
        self.description = description
        self.active = active
        self.filter = filter
        self.columns = columns
        self.rows = rows
        self.timer = timer
        self.visibility = visibility

    def create(self, cancel=False):
        sel.force_navigate("reports_widgets_report_add")
        fill(self.form, self.__dict__, action=form_buttons.cancel if cancel else form_buttons.add)
        flash.assert_no_errors()

    def update(self, updates):
        sel.force_navigate("reports_widgets_report_edit", context={"widget": self})
        fill(self.form, updates, action=form_buttons.save)
        flash.assert_no_errors()

    def delete(self, cancel=False):
        sel.force_navigate("reports_widgets_report", context={"widget": self})
        toolbar.select("Configuration", "Delete this Widget from the Database", invokes_alert=True)
        sel.handle_alert(cancel)
        flash.assert_no_errors()
class ReportWidget(Widget):
    form = Form(fields=[
        ("title", Input("title")),
        ("description", Input("description")),
        ("active", Input("enabled")),
        ("filter",
         ShowingInputs(Select("//select[@id='filter_typ']"),
                       Select("//select[@id='subfilter_typ']"),
                       Select("//select[@id='repfilter_typ']"),
                       min_values=3)),  # Might be abstracted out too
        ("columns",
         ShowingInputs(Select("//select[@id='chosen_pivot1']"),
                       Select("//select[@id='chosen_pivot2']"),
                       Select("//select[@id='chosen_pivot3']"),
                       Select("//select[@id='chosen_pivot4']"),
                       min_values=1)),
        ("rows", Select("//select[@id='row_count']")),
        ("timer", Timer()),
        ("visibility", visibility_obj),
    ])
    TITLE = "Reports"
    pretty_attrs = ['description', 'filter', 'visibility']

    def __init__(self,
                 title,
                 description=None,
                 active=None,
                 filter=None,
                 columns=None,
                 rows=None,
                 timer=None,
                 visibility=None):
        self.title = title
        self.description = description
        self.active = active
        self.filter = filter
        self.columns = columns
        self.rows = rows
        self.timer = timer
        self.visibility = visibility
class Schedule(Updateable):
    """Represents a schedule in Intelligence/Reports/Schedules.

    Args:
        name: Schedule name.
        description: Schedule description.
        filter: 3-tuple with filter selection (see the UI).
        active: Whether is this schedule active.
        run: Specifies how often this schedule runs. It can be either string "Once", or a tuple,
            which maps to the two selects in UI ("Hourly", "Every hour")...
        time_zone: Specify time zone.
        start_date: Specify the start date.
        start_time: Specify the start time either as a string ("0:15") or tuple ("0", "15")
        send_email: If specifies, turns on e-mail sending. Can be string, or list or set.
    """
    form = Form(fields=[
        ("name", "//input[@id='name']"),
        ("description", "//input[@id='description']"),
        ("active", "//input[@id='enabled']"),
        ("filter", ShowingInputs(
            Select("//select[@id='filter_typ']"),
            Select("//select[@id='subfilter_typ']"),
            Select("//select[@id='repfilter_typ']"),
            min_values=3
        )),
        ("timer", Timer()),
        ("send_email", "//input[@id='send_email_cb']"),
        ("emails", EmailSelectForm())
    ])

    _run_mapping = {
        "Once": None,
        "Hourly": "run_hours",
        "Daily": "run_days",
        "Weekly": "run_weekly",
        "Monthly": "run_months"
    }

    info_block = InfoBlock("detail")

    def __init__(
            self,
            name,
            description,
            filter,
            active=None,
            timer=None,
            send_email=None):
        self.name = name
        self.description = description
        self.filter = filter
        self.active = active
        self.timer = timer
        self.send_email = send_email

    @property
    def exists(self):
        schedules = cfmedb["miq_schedules"]
        return cfmedb.session\
            .query(schedules.name)\
            .filter(schedules.name == self.name)\
            .count() > 0

    def _fill(self, action):
        fill(
            self.form,
            self._create_fill_dict(),
            action=action
        )

    def create(self, cancel=False):
        sel.force_navigate("schedule_add")
        self._fill(form_buttons.add if not cancel else form_buttons.cancel)
        flash.assert_no_errors()
        assert self.exists, "Schedule does not exist!"

    def update(self, updates):
        sel.force_navigate("schedule_edit", context={"schedule": self})
        fill(self.form, updates, action=form_buttons.save)
        flash.assert_no_errors()
        assert self.exists, "Schedule does not exist!"

    def delete(self, cancel=False):
        sel.force_navigate("schedule", context={"schedule": self})
        cfg_btn("Delete this Schedule from the Database", invokes_alert=True)
        sel.handle_alert(cancel)
        flash.assert_no_errors()
        assert not self.exists, "Schedule does not exist!"

    def table_item(self, item):
        """Works both up- and downstream.

        I think this should be incorporated into InfoBlock somehow. Currently there is the fieldset
        issue.
        """
        return "//td[preceding-sibling::td[contains(@class, 'key') and .='{}']]".format(item)

    def queue(self, wait_for_finish=False):
        """Queue this schedule.

        Args:
            wait_for_finish: If True, then this function blocks until the action is finished.
        """
        if not self.exists:
            self.create()
        sel.force_navigate("schedule", context={"schedule": self})
        last_run = sel.text(self.table_item("Last Run Time")).strip()
        cfg_btn("Queue up this Schedule to run now")
        flash.assert_no_errors()
        if wait_for_finish:
            wait_for(
                lambda: sel.text(self.table_item("Last Run Time")).strip() != last_run,
                delay=2,
                fail_func=lambda: toolbar.select("Reload current display"),
                message="wait for report queue finish"
            )

    def _create_fill_dict(self):
        """Handle the values, create dictionary for form"""
        # Simple values come
        fields = {
            "name": self.name,
            "description": self.description,
            "active": self.active,
            "filter": self.filter,
            "timer": self.timer,
        }

        # Send e-mail
        if self.send_email is not None:
            fields["send_email"] = True
            fields["emails"] = self.send_email

        return fields

    # Methods for all schedules
    @classmethod
    def _select_schedules(cls, schedules):
        """Select schedules in the table.

        Args:
            schedules: Schedules to select.
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        sel.force_navigate("schedules")
        failed_selections = []
        for schedule in schedules:
            if isinstance(schedule, cls):
                name = schedule.name
            else:
                name = str(schedule)
            if not schedules_table.select_row("Name", name):
                failed_selections.append(name)
        if failed_selections:
            raise NameError("These schedules were not found: {}.".format(
                ", ".join(failed_selections)
            ))

    @classmethod
    def _action_on_schedules(cls, action, schedules, cancel=None):
        """Select schedules and perform an action on them

        Args:
            action: Action in Configuration to perform.
            schedules: List of schedules.
            cancel: If specified, the nalert is expected after clicking on action and value of the
                variable specifies handling behaviour.
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        cls._select_schedules(schedules)
        if cancel is None:
            cfg_btn(action)
        else:
            cfg_btn(action, invokes_alert=True)
            sel.handle_alert(bool(cancel))
        flash.assert_no_errors()

    @classmethod
    def enable_schedules(cls, *schedules):
        """Select and enable specified schedules.

        Args:
            *schedules: Schedules to enable. Can be objects or strings.
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        return cls._action_on_schedules("Enable the selected Schedules", schedules)

    @classmethod
    def disable_schedules(cls, *schedules):
        """Select and disable specified schedules.

        Args:
            *schedules: Schedules to disable. Can be objects or strings.
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        return cls._action_on_schedules("Disable the selected Schedules", schedules)

    @classmethod
    def queue_schedules(cls, *schedules):
        """Select and queue specified schedules.

        Args:
            *schedules: Schedules to queue. Can be objects or strings.
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        return cls._action_on_schedules("Queue up selected Schedules to run now", schedules)

    @classmethod
    def delete_schedules(cls, *schedules, **kwargs):
        """Select and delete specified schedules from VMDB.

        Args:
            *schedules: Schedules to delete. Can be objects or strings.
        Keywords:
            cancel: Whether to cancel the deletion (Default: False)
        Raises: :py:class:`NameError` when some of the schedules were not found.
        """
        return cls._action_on_schedules(
            "Delete the selected Schedules from the VMDB", schedules, kwargs.get("cancel", False)
        )
Exemple #4
0
 ],
 tab_fields={
     "Columns": [
         ("base_report_on", select(id="chosen_model")),
         ("report_fields", MultiBoxSelect(
             select(id="available_fields"),
             select(id="selected_fields"),
             button(alt="Move selected fields up"),
             button(alt="Move selected fields down"),
         )),
         ("cancel_after", select(id="chosen_queue_timeout")),
     ],
     "Consolidation": [
         ("group_records", ShowingInputs(
             select(id="chosen_pivot1"),
             select(id="chosen_pivot2"),
             select(id="chosen_pivot3"),
         )),
         ("calculations_grouped", RecordGrouper(
             table_in_object("Specify Calculations of Numeric Values for Grouped Records"))),
     ],
     "Formatting": [
         ("page_size", select(id="pdf_page_size")),
         ("headers",
             ColumnHeaderFormatTable(table_in_object("Specify Column Headers and Formats"))),
     ],
     "Styling": [
         ("column_styles", ColumnStyleTable("styling_div")),
     ],
     "Filter": [
         ("filter", Expression()),
Exemple #5
0
            accordion.tree("Dashboard Widgets", "All Widgets", "RSS Feeds", ctx["widget"].title),
            {
                "reports_widgets_rss_feed_delete":
                lambda _: toolbar.select("Configuration", "Delete this Widget from the Database"),

                "reports_widgets_rss_feed_edit":
                lambda _: toolbar.select("Configuration", "Edit this Widget"),
            }
        ],
    }
)


visibility_obj = ShowingInputs(
    Select("//select[@id='visibility_typ']"),
    CheckboxSelect("//div[@id='form_role_visibility']//table/"
                   "tbody/tr/td[not(contains(@class, 'key'))]/table"),
    min_values=1
)


class MenuWidget(Updateable):
    form = Form(fields=[
        ("title", "//input[@id='title']"),
        ("description", "//input[@id='description']"),
        ("active", "//input[@id='enabled']"),
        ("shortcuts", MenuShortcuts("//select[@id='add_shortcut']")),
        ("visibility", visibility_obj),
    ])

    def __init__(self, title, description=None, active=None, shortcuts=None, visibility=None):
        self.title = title
Exemple #6
0
 "Columns": [
     ("base_report_on", select(id="chosen_model")),
     ("report_fields",
      MultiBoxSelect(
          select(id="available_fields"),
          select(id="selected_fields"),
          img(alt="Move selected fields up"),
          img(alt="Move selected fields down"),
      )),
     ("cancel_after", select(id="chosen_queue_timeout")),
 ],
 "Consolidation": [
     ("group_records",
      ShowingInputs(
          select(id="chosen_pivot1"),
          select(id="chosen_pivot2"),
          select(id="chosen_pivot3"),
      )),
     ("calculations_grouped",
      RecordGrouper(
          table_in_object(
              "Specify Calculations of Numeric Values for Grouped Records"
          ))),
 ],
 "Formatting": [
     ("page_size", select(id="pdf_page_size")),
     ("headers",
      ColumnHeaderFormatTable(
          table_in_object("Specify Column Headers and Formats"))),
 ],
 "Styling": [
Exemple #7
0
                                       "RSS Feeds", ctx["widget"].title),
            {
                "reports_widgets_rss_feed_delete":
                lambda _: toolbar.select(
                    "Configuration", "Delete this Widget from the Database"),
                "reports_widgets_rss_feed_edit":
                lambda _: toolbar.select("Configuration", "Edit this Widget"),
            }
        ],
    })

visibility_obj = ShowingInputs(
    Select("//select[@id='visibility_typ']"),
    CheckboxSelect({
        version.LOWEST:
        "//td[normalize-space(.)='User Roles']/../td/table",
        "5.5":
        "//label[normalize-space(.)='User Roles']/../div/table"
    }),
    min_values=1)


class Widget(Updateable, Pretty):
    TITLE = None
    DETAIL_PAGE = None
    WAIT_STATES = {"Queued", "Running"}
    status_info = InfoBlock("Status")

    @property
    def on_widget_page(self):
        return sel.is_displayed(
Exemple #8
0
            fill("input#{}{}".format(self.vp, i), data[key])


@fill.method((AVPForm, Mapping))
def _fill_avp_form(avp, data):
    avp.fill(data)


sim_form = Form(fields=[
    ("instance", Select("select#instance_name")),
    ("message", Input("object_message")),
    ("request", Input("object_request")),
    ("attribute",
     ShowingInputs(
         Select("select#target_class"),
         Select("select#target_id"),
         min_values=1,
     )),
    ("execute_methods", Input("readonly")),
    ("avp", AVPForm()),
])

sim_btn = form_buttons.FormButton(
    "Submit Automation Simulation with the specified options")


def simulate(**data):
    """Runs the simulation of specified Automate object.

    Args:
        **data: See :py:data:`sim_form` for keyword reference