Esempio n. 1
0
from utils.pretty import Pretty

# Page specific locators
details_page = Region(infoblock_type='detail')

page_title_loc = '//div[@id="center_div" or @id="main-content"]//h1'

properties_form = Form(fields=[
    ('name_text', Input("name")),
    ('hostname_text', Input("hostname")),
    ('ipaddress_text', Input("ipaddress"), {
        "removed_since": "5.4.0.0.15"
    }),
    ('custom_ident_text', Input("custom")),
    ('host_platform', {
        version.LOWEST: Select('//select[@id="user_assigned_os"]'),
        '5.5': AngularSelect('user_assigned_os')
    }),
    ('ipmi_address_text', Input("ipmi_address")),
    ('mac_address_text', Input("mac_address")),
])

credential_form = Form(fields=[
    ('default_button', "//div[@id='auth_tabs']/ul/li/a[@href='#default']"),
    ('default_principal', Input("default_userid")),
    ('default_secret', Input("default_password")),
    ('default_verify_secret', Input("default_verify")),
    ('ipmi_button', "//div[@id='auth_tabs']/ul/li/a[@href='#ipmi']"),
    ('ipmi_principal', Input("ipmi_userid")),
    ('ipmi_secret', Input("ipmi_password")),
    ('ipmi_verify_secret', Input("ipmi_verify")),
from cfme.web_ui import toolbar as tb
from utils.update import Updateable
from utils.pretty import Pretty
from utils import error

cfg_btn = partial(tb.select, "Configuration")
accordion_tree = partial(accordion.tree, "Orchestration Templates")

dialog_form = Form(
    fields=[('dialog_name',
             Input("dialog_name")), ('save_button', form_buttons.save)])

create_template_form = Form(fields=[
    ('template_name', Input("name")),
    ('description', "textarea#description"),
    ("template_type", Select("select#type")),
    ('content',
     ScriptBox(ta_locator="//div[@id='basic_info_div']/div/div"
               "/div/div/div/div/div/div/pre/span")),
    ('add_button', form_buttons.add),
    ('edit_button', form_buttons.save),
])


def _orch_templates_create_dialog(context):
    accordion_tree('All Orchestration Templates', context['template_type'],
                   context['template_name'])
    cfg_btn('Create Service Dialog from Orchestration Template')


menu.nav.add_branch(
Esempio n. 3
0
    load_filter_dialog_button=FormButton("Load the filter shown above"),
    cancel_load_filter_dialog_button=FormButton("Cancel the load"),
    save_filter_dialog_button=FormButton("Save the current search"),
    cancel_save_filter_dialog_button=FormButton("Cancel the save"),

    # If user input requested, this window appears
    quick_search_box="//div[@id='quicksearchbox']",

    # With these buttons
    userinput_apply_filter_button=FormButton(
        "Apply the current filter (Enter)"),
    userinput_cancel_button=FormButton("Cancel (Esc)"),

    # Elements in Load dialog
    # Selects for selecting the filter
    saved_filter=Select("select#chosen_search"),
    report_filter=Select("select#chosen_report"),

    # Elements in Save dialog
    save_name=Input("search_name"),
    global_search=Input("search_type"),

    # On the main page, this link clears the filters
    clear_advanced_search="//a[contains(@href, 'adv_search_clear')]",
))


def _answering_function(answers_dict, text, element):
    """A generic answering function for filling user-input elements

    Args:
Esempio n. 4
0
 def select(self):
     return Select(self._select_loc)
Esempio n. 5
0
from utils import version
from utils.pretty import Pretty

# Specific Add button
add_provider_button = form_buttons.FormButton("Add this Cloud Provider")

# Forms
discover_form = Form(
    fields=[('username',
             "#userid"), ('password',
                          "#password"), ('password_verify', "#verify"),
            ('start_button',
             form_buttons.FormButton("Start the Host Discovery"))])

properties_form = Form(fields=[
    ('type_select', Select("select#server_emstype")),
    ('name_text', Input("name")),
    ('hostname_text', Input("hostname")),
    ('ipaddress_text', Input("ipaddress"), {
        "removed_since": "5.4.0.0.15"
    }),
    ('amazon_region_select',
     Select({
         version.LOWEST: "select#hostname",
         "5.3.0.14": "select#provider_region",
     })),
    ('api_port', Input("port")),
])

details_page = Region(infoblock_type='detail')
Esempio n. 6
0
class BaseVM(Pretty, Updateable, PolicyProfileAssignable, Taggable):
    """Base VM and Template class that holds the largest common functionality between VMs,
    instances, templates and images.

    In order to inherit these, you have to implement the ``on_details`` method.
    """
    pretty_attrs = ['name', 'provider', 'template_name']
    _registered_types = {}

    # Forms
    edit_form = Form(fields=[
        ('custom_ident', Input("custom_1")),
        ('description_tarea', "//textarea[@id='description']"),
        ('parent_sel', {
            version.LOWEST: Select("//select[@name='chosen_parent']"),
            "5.5": AngularSelect("chosen_parent")
        }),
        ('child_sel', Select("//select[@id='kids_chosen']", multi=True)),
        ('vm_sel', Select("//select[@id='choices_chosen']", multi=True)),
        ('add_btn', "//img[@alt='Move selected VMs to left']"),
        ('remove_btn', "//img[@alt='Move selected VMs to right']"),
        ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
    ])

    ###
    # Factory class methods
    #
    @classmethod
    def register_for_provider_type(cls, *provider_types):
        """This method is used to assign the subclasses to certain providers.

        Usage as follows:

        .. code-block:: python

           @BaseVM.register_for_provider_type("cloud")
           class Instance(BaseVM):
               pass

           @BaseVM.register_for_provider_type("ec2")
           class EC2Instance(BaseVM):
               pass

           @BaseVM.register_for_provider_type("infra")
           class VM(BaseVM):
               pass

        You can use both the types of providers and also the general classes (infra, cloud).

        Args:
            *provider_types: The provider types to assign this class to
        """
        def f(klass):
            for provider_type in provider_types:
                if provider_type not in cls._registered_types:
                    cls._registered_types[provider_type] = {}
                if issubclass(klass, _TemplateMixin):
                    cls._registered_types[provider_type]["template"] = klass
                else:
                    cls._registered_types[provider_type]["vm"] = klass
            return klass

        return f

    @classmethod
    def factory(cls, vm_name, provider, template_name=None, template=False):
        """Factory class method that determines the correct subclass for given provider.

        For reference how does that work, refer to :py:meth:`register_for_provider_type`

        Args:
            vm_name: Name of the VM/Instance as it appears in the UI
            provider: The provider object (not the string!)
            template_name: Source template name. Useful when the VM/Instance does not exist and you
                want to create it.
            template: Whether the generated object class should be VM/Instance or a template class.
        """
        # Ensure the classes are loaded:
        import cfme.cloud.instance  # NOQA
        import cfme.infrastructure.virtual_machines  # NOQA
        try:
            return (cls._registered_types[provider.type]
                    ["template" if template else "vm"](vm_name, provider,
                                                       template_name))
        except KeyError:
            # Matching via provider type failed. Maybe we have some generic classes for infra/cloud?
            try:
                return (cls._registered_types[provider.category]
                        ["template" if template else "vm"](vm_name, provider,
                                                           template_name))
            except KeyError:
                raise UnknownProviderType(
                    'Unknown type of cloud provider CRUD object: {}'.format(
                        provider.__class__.__name__))

    ###
    # To be set or implemented
    #
    ALL_LIST_LOCATION = None
    TO_OPEN_EDIT = None  # Name of the item in Configuration that puts you in the form
    QUADICON_TYPE = "vm"
    # Titles of the delete buttons in configuration
    REMOVE_MULTI = "Remove selected items from the VMDB"  # For multiple items
    REMOVE_SINGLE = "Remove from the VMDB"  # For single item

    ###
    # Shared behaviour
    #
    def __init__(self, name, provider, template_name=None):
        super(BaseVM, self).__init__()
        if type(self) in {BaseVM, VM, Template}:
            raise NotImplementedError('This class cannot be instantiated.')
        self.name = name
        self.provider = provider
        self.template_name = template_name

        if not hasattr(self, "on_details"):
            raise NotImplementedError(
                "You need to implement on_details method in {}!".format(
                    type(self).__name__))

    ###
    # Properties
    #
    @property
    def is_vm(self):
        return not isinstance(self, _TemplateMixin)

    @property
    def quadicon_type(self):
        return self.QUADICON_TYPE

    ###
    # Methods
    #
    def check_compliance(self):
        """Clicks the Check compliance button."""
        self.load_details(refresh=True)
        pol_btn("Check Compliance of Last Known Configuration",
                invokes_alert=True)
        sel.handle_alert()
        flash.assert_no_errors()

    @contextmanager
    def check_compliance_wrapper(self, timeout=240):
        """This wrapper takes care of waiting for the compliance status to change

        Args:
            timeout: Wait timeout in seconds.
        """
        self.load_details(refresh=True)
        original_state = self.compliance_status
        yield
        wait_for(lambda: self.compliance_status != original_state,
                 num_sec=timeout,
                 delay=5,
                 message="compliance of {} checked".format(self.name),
                 fail_func=lambda: toolbar.select("Reload"))

    def check_compliance_and_wait(self, timeout=240):
        """Initiates compliance check and waits for it to finish."""
        with self.check_compliance_wrapper(timeout=timeout):
            self.check_compliance()
        return self.compliant

    @property
    def compliance_status(self):
        """Returns the title of the compliance infoblock. The title contains datetime so it can be
        compared.

        Returns:
            :py:class:`NoneType` if no title is present (no compliance checks before), otherwise str
        """
        self.load_details(refresh=True)
        return InfoBlock("Compliance", "Status").title

    @property
    def compliant(self):
        """Check if the VM is compliant

        Returns:
            :py:class:`NoneType` if the VM was never verified, otherwise :py:class:`bool`
        """
        text = self.get_detail(properties=("Compliance",
                                           "Status")).strip().lower()
        if text == "never verified":
            return None
        elif text.startswith("non-compliant"):
            return False
        elif text.startswith("compliant"):
            return True
        else:
            raise ValueError(
                "{} is not a known state for compliance".format(text))

    def delete(self, cancel=False, from_details=False):
        """Deletes the VM/Instance from the VMDB.

        Args:
            cancel: Whether to cancel the action in the alert.
            from_details: Whether to use the details view or list view.
        """
        if from_details:
            self.load_details(refresh=True)
            cfg_btn(self.REMOVE_SINGLE, invokes_alert=True)
        else:
            self.find_quadicon(mark=True)
            cfg_btn(self.REMOVE_MULTI, invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def exists(self):
        """Checks presence of the quadicon in the CFME."""
        try:
            self.find_quadicon()
            return True
        except VmOrInstanceNotFound:
            return False

    def find_quadicon(self,
                      do_not_navigate=False,
                      mark=False,
                      refresh=True,
                      from_any_provider=False):
        """Find and return a quadicon belonging to a specific vm

        Args:
            from_any_provider: Whether to look for it anywhere (root of the tree). Useful when
                looking up archived or orphaned VMs

        Returns: :py:class:`cfme.web_ui.Quadicon` instance
        Raises: VmOrInstanceNotFound
        """
        quadicon = Quadicon(self.name, self.quadicon_type)
        if not do_not_navigate:
            if from_any_provider:
                sel.force_navigate(self.ALL_LIST_LOCATION)
            elif self.is_vm:
                self.provider.load_all_provider_vms()
            else:
                self.provider.load_all_provider_templates()
            toolbar.select('Grid View')
        elif refresh:
            sel.refresh()
        if not paginator.page_controls_exist():
            if self.is_vm:
                raise VmOrInstanceNotFound("VM '{}' not found in UI!".format(
                    self.name))
            else:
                raise TemplateNotFound("Template '{}' not found in UI!".format(
                    self.name))

        # this is causing some issues in 5.5.0.9, commenting out for a bit
        # paginator.results_per_page(1000)
        for page in paginator.pages():
            if sel.is_displayed(quadicon, move_to=True):
                if mark:
                    sel.check(quadicon.checkbox())
                return quadicon
        else:
            raise VmOrInstanceNotFound("VM '{}' not found in UI!".format(
                self.name))

    def get_detail(self, properties=None, icon_href=False):
        """Gets details from the details infoblock

        The function first ensures that we are on the detail page for the specific VM/Instance.

        Args:
            properties: An InfoBlock title, followed by the Key name, e.g. "Relationships", "Images"

        Returns:
            A string representing the contents of the InfoBlock's value.
        """
        self.load_details(refresh=True)
        if icon_href:
            return InfoBlock.icon_href(*properties)
        else:
            return InfoBlock.text(*properties)

    @classmethod
    def get_first_vm_title(cls, do_not_navigate=False, provider=None):
        """Get the title of first VM/Instance."""
        if not do_not_navigate:
            if provider is None:
                sel.force_navigate(cls.ALL_LIST_LOCATION)
            else:
                provider.load_all_provider_vms()
        return Quadicon.get_first_quad_title()

    @property
    def last_analysed(self):
        """Returns the contents of the ``Last Analysed`` field in summary"""
        return self.get_detail(properties=('Lifecycle',
                                           'Last Analyzed')).strip()

    def load_details(self, refresh=False):
        """Navigates to an VM's details page.

        Args:
            refresh: Refreshes the VM page if already there

        Raises:
            VmOrInstanceNotFound:
                When unable to find the VM passed
        """
        if not self.on_details():
            logger.debug("load_details: not on details already")
            sel.click(self.find_quadicon())
        else:
            if refresh:
                toolbar.refresh()

    def open_edit(self):
        """Loads up the edit page of the object."""
        self.load_details(refresh=True)
        cfg_btn(self.TO_OPEN_EDIT)

    def open_timelines(self):
        self.load_details(refresh=True)
        mon_btn("Timelines")

    def rediscover(self):
        """Deletes the VM from the provider and lets it discover again"""
        self.delete(from_details=True)
        self.wait_for_delete()
        self.provider.refresh_provider_relationships()
        self.wait_to_appear()

    def rediscover_if_analysis_data_present(self):
        """Rediscovers the object if it has some analysis data present.

        Returns:
            Boolean if the rediscovery happened.
        """
        if self.last_analysed.lower() != 'never':
            self.rediscover()
            return True
        return False

    def refresh_relationships(self, from_details=False, cancel=False):
        """Executes a refresh of relationships.

        Args:
            from_details: Whether or not to perform action from instance details page
            cancel: Whether or not to cancel the refresh relationships action
        """
        if from_details:
            self.load_details()
        else:
            self.find_quadicon(mark=True)
        cfg_btn('Refresh Relationships and Power States', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def retirement_date(self):
        """Returns the retirement date of the selected machine.

        Returns:
            :py:class:`NoneType` if there is none, or :py:class:`utils.timeutil.parsetime`
        """
        date_str = self.get_detail(properties=("Lifecycle",
                                               "Retirement Date")).strip()
        if date_str.lower() == "never":
            return None
        return parsetime.from_american_date_only(date_str)

    def smartstate_scan(self, cancel=False, from_details=False):
        """Initiates fleecing from the UI.

        Args:
            cancel: Whether or not to cancel the refresh relationships action
            from_details: Whether or not to perform action from instance details page
        """
        if from_details:
            self.load_details(refresh=True)
        else:
            self.find_quadicon(mark=True)
        cfg_btn('Perform SmartState Analysis', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    def wait_to_disappear(self, timeout=600, load_details=True):
        """Wait for a VM to disappear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
        """
        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=30,
                 fail_func=sel.refresh,
                 fail_condition=True)

    wait_for_delete = wait_to_disappear  # An alias for more fitting verbosity

    def wait_to_appear(self, timeout=600, load_details=True):
        """Wait for a VM to appear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
            from_details: when found, should it load the vm details
        """
        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=30,
                 fail_func=sel.refresh)
        if load_details:
            self.load_details()

    def set_ownership(self,
                      user=None,
                      group=None,
                      click_cancel=False,
                      click_reset=False):
        """Set ownership of the VM/Instance or Template/Image"""
        sel.click(self.find_quadicon(False, False, False))
        cfg_btn('Set Ownership')
        if click_reset:
            action = form_buttons.reset
            msg_assert = lambda: flash.assert_message_match(
                'All changes have been reset')
        elif click_cancel:
            action = form_buttons.cancel
            msg_assert = lambda: flash.assert_success_message(
                'Set Ownership was cancelled by the user')
        else:
            action = form_buttons.save
            msg_assert = lambda: flash.assert_success_message(
                'Ownership saved for selected Virtual Machine')
        fill(set_ownership_form, {
            'user_name': user,
            'group_name': group
        },
             action=action)
        msg_assert()

    def unset_ownership(self):
        """Unset ownership of the VM/Instance or Template/Image"""
        # choose the vm code comes here
        sel.click(self.find_quadicon(False, False, False))
        cfg_btn('Set Ownership')
        fill(set_ownership_form, {
            'user_name': '<No Owner>',
            'group_name': '<No Group>'
        },
             action=form_buttons.save)
        flash.assert_success_message(
            'Ownership saved for selected Virtual Machine')
Esempio n. 7
0
)


snapshot_form = Form(
    fields=[
        ('name', Input('name')),
        ('description', Input('description')),
        ('snapshot_memory', Input('snap_memory')),
        ('create_button', create_button),
        ('cancel_button', form_buttons.cancel)
    ])


retirement_date_form = Form(fields=[
    ('retirement_date_text', Calendar("miq_date_1")),
    ('retirement_warning_select', Select("//select[@id='retirement_warn']"))
])

retire_remove_button = "//span[@id='remove_button']/a/img"

match_page = partial(match_location, controller='vm_infra', title='Virtual Machines')


drift_table = CheckboxTable("//th[normalize-space(.)='Timestamp']/ancestor::table[1]")


class InfraGenericDetailsToolbar(View):
    reload = Button(title='Reload current display')
    configuration = Dropdown('Configuration')
    policy = Dropdown('Policy')
    monitoring = Dropdown("Monitoring")
Esempio n. 8
0
class Schedule(Updateable, Pretty, Navigatable):
    """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("name")), ("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)), ("timer", Timer()),
                        ("send_email",
                         Input("send_email_cb")), ("emails",
                                                   EmailSelectForm())])

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

    pretty_attrs = ['name', 'filter']

    def __init__(self,
                 name,
                 description,
                 filter,
                 active=None,
                 timer=None,
                 send_email=None,
                 appliance=None):
        Navigatable.__init__(self, appliance)
        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 = self.appliance.db["miq_schedules"]
        return self.appliance.db.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):
        navigate_to(self, '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):
        navigate_to(self, 'Edit')
        fill(self.form, updates, action=form_buttons.save)
        flash.assert_no_errors()
        assert self.exists, "Schedule does not exist!"

    def delete(self, cancel=False):
        navigate_to(self, 'Delete')
        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 (version.pick({
            version.LOWEST:
            "//td[preceding-sibling::td[contains(@class, 'key')"
            " and normalize-space(.)='{}']]",
            "5.5":
            "//label[contains(@class, 'control-label')"
            " and normalize-space(.)='{}']/../div/p"
        }).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()
        navigate_to(self, 'Details')
        last_run = sel.text(self.table_item("Last Run Time")).strip()
        navigate_to(self, 'Queue')
        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.
        """
        navigate_to(cls, 'All')
        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.
            cancel: (kwarg) 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))
Esempio n. 9
0
 def select(self):
     return version.pick({
         version.LOWEST: Select("select#{}".format(self._select_name)),
         "5.5": AngularSelect(self._select_name)})
Esempio n. 10
0
class Visual(Updateable):

    pretty_attrs = ['name']

    item_form = Form(fields=[
        ('grid_view', {
            version.LOWEST: Select('//select[@id="perpage_grid"]'),
            "5.5": AngularSelect('perpage_grid')
        }),
        ('tile_view', {
            version.LOWEST: Select('//select[@id="perpage_tile"]'),
            "5.5": AngularSelect("perpage_tile")
        }),
        ('list_view', {
            version.LOWEST: Select('//select[@id="perpage_list"]'),
            "5.5": AngularSelect("perpage_list")
        }),
        ('reports', {
            version.LOWEST: Select('//select[@id="perpage_reports"]'),
            "5.5": AngularSelect("perpage_reports")
        }),
    ])

    startpage_form = Form(
        fields=[('login_page', {
            version.LOWEST: Select('//select[@id="start_page"]'),
            "5.5": AngularSelect("start_page")
        })])

    quadicons_form = Form(fields=[
        ('infra_provider_quad', Input("quadicons_ems")),
        ('cloud_provider_quad', Input("quadicons_ems_cloud")),
        ('host_quad', Input("quadicons_host")),
        ('datastore_quad', Input("quadicons_storage")),
        ('datastoreitem_quad', Input("quadicons_storageitem")),
        ('vm_quad', Input("quadicons_vm")),
        ('vmitem_quad', Input("quadicons_vmitem")),
        ('template_quad', Input("quadicons_miq_template")),
    ])

    display_form = Form(fields=[
        ('chart_theme', {
            version.LOWEST: Select('//select[@id="display_reporttheme"]'),
            "5.5": AngularSelect("display_reporttheme")
        }),
        ('time_zone', {
            version.LOWEST: Select('//select[@id="display_timezone"]'),
            "5.5": AngularSelect("display_timezone")
        }),
    ])

    save_button = form_buttons.FormButton("Add this Time Profile")

    @property
    def grid_view_limit(self):
        sel.force_navigate("my_settings_visual")
        return int(self.item_form.grid_view.first_selected_option_text)

    @grid_view_limit.setter
    def grid_view_limit(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.item_form.grid_view, str(value))
        sel.click(form_buttons.save)

    @property
    def tile_view_limit(self):
        sel.force_navigate("my_settings_visual")
        return int(self.item_form.tile_view.first_selected_option_text)

    @tile_view_limit.setter
    def tile_view_limit(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.item_form.tile_view, str(value))
        sel.click(form_buttons.save)

    @property
    def list_view_limit(self):
        sel.force_navigate("my_settings_visual")
        return int(self.item_form.list_view.first_selected_option_text)

    @list_view_limit.setter
    def list_view_limit(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.item_form.list_view, str(value))
        sel.click(form_buttons.save)

    @property
    def report_view_limit(self):
        sel.force_navigate("my_settings_visual")
        return int(self.item_form.reports.first_selected_option_text)

    @report_view_limit.setter
    def report_view_limit(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.item_form.reports, str(value))
        sel.click(form_buttons.save)

    @property
    def login_page(self):
        sel.force_navigate("my_settings_visual")
        return int(self.startpage_form.login_page.first_selected_option_text)

    @login_page.setter
    def login_page(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.startpage_form.login_page, str(value))
        sel.click(form_buttons.save)

    @property
    def infra_provider_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.infra_provider_quad

    @infra_provider_quad.setter
    def infra_provider_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.infra_provider_quad, str(value))
        sel.click(form_buttons.save)

    @property
    def host_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.host_quad

    @host_quad.setter
    def host_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.host_quad, str(value))
        sel.click(form_buttons.save)

    @property
    def datastore_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.datastore_quad

    @datastore_quad.setter
    def datastore_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.datastore_quad, str(value))
        sel.click(form_buttons.save)

    @property
    def vm_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.vm_quad

    @vm_quad.setter
    def vm_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.vm_quad, str(value))
        sel.click(form_buttons.save)

    @property
    def template_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.template_quad

    @template_quad.setter
    def template_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.template_quad, str(value))
        sel.click(form_buttons.save)

    def check_image_exists(self):
        name = Quadicon.get_first_quad_title()
        quad = Quadicon(name, None)
        return quad.check_for_single_quadrant_icon

    @property
    def cloud_provider_quad(self):
        sel.force_navigate("my_settings_visual")
        return self.cloud_provider_quad

    @cloud_provider_quad.setter
    def cloud_provider_quad(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.quadicons_form.cloud_provider_quad, str(value))
        sel.click(form_buttons.save)

    @property
    def timezone(self):
        sel.force_navigate("my_settings_visual")
        return self.display_form.time_zone.first_selected_option_text

    @timezone.setter
    def timezone(self, value):
        sel.force_navigate("my_settings_visual")
        fill(self.display_form.time_zone, str(value))
        sel.click(form_buttons.save)
Esempio n. 11
0
class Timeprofile(Updateable):
    timeprofile_form = Form(fields=[
        ("description", Input("description")),
        ("scope", {
            version.LOWEST: Select("select#profile_type"),
            "5.5": AngularSelect("profile_type")
        }),
        ("timezone", {
            version.LOWEST: Select("select#profile_tz"),
            "5.5": AngularSelect("profile_tz")
        }),
        ("days", Input("all_days")),
        ("hours", Input("all_hours")),
    ])

    save_button = form_buttons.FormButton("Add this Time Profile")

    def __init__(self,
                 description=None,
                 scope=None,
                 days=None,
                 hours=None,
                 timezone=None):
        self.description = description
        self.scope = scope
        self.days = days
        self.hours = hours
        self.timezone = timezone

    def create(self):
        sel.force_navigate('timeprofile_new')
        fill(self.timeprofile_form, {
            'description': self.description,
            'scope': self.scope,
            'days': self.days,
            'hours': self.hours,
            'timezone': self.timezone,
        },
             action=self.save_button)
        flash.assert_success_message('Time Profile "{}" was added'.format(
            self.description))

    def update(self, updates):
        sel.force_navigate("timeprofile_edit", context={"timeprofile": self})
        fill(self.timeprofile_form, {
            'description': updates.get('description'),
            'scope': updates.get('scope'),
            'timezone': updates.get('timezone')
        },
             action=form_buttons.save)
        flash.assert_success_message('Time Profile "{}" was saved'.format(
            updates.get('description', self.description)))

    def copy(self):
        sel.force_navigate("my_settings_time_profiles")
        row = timeprofile_table.find_row_by_cells(
            {'description': self.description})
        sel.check(sel.element(".//input[@type='checkbox']", root=row[0]))
        cfg_btn('Copy selected Time Profile')
        new_timeprofile = Timeprofile(description=self.description + "copy",
                                      scope=self.scope)
        fill(self.timeprofile_form, {
            'description': new_timeprofile.description,
            'scope': new_timeprofile.scope
        },
             action=self.save_button)
        flash.assert_success_message('Time Profile "{}" was added'.format(
            new_timeprofile.description))
        return new_timeprofile

    def delete(self):
        sel.force_navigate("my_settings_time_profiles")
        row = timeprofile_table.find_row_by_cells(
            {'description': self.description})
        sel.check(sel.element(".//input[@type='checkbox']", root=row[0]))
        cfg_btn('Delete selected Time Profiles', invokes_alert=True)
        sel.handle_alert()
        flash.assert_success_message(
            'Time Profile "{}": Delete successful'.format(self.description))
Esempio n. 12
0
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 = "Report"
    pretty_attrs = ['description', 'filter', 'visibility']
    DETAIL_PAGE = "reports_widgets_report"

    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):
        self.go_to_detail()
        toolbar.select("Configuration",
                       "Delete this Widget from the Database",
                       invokes_alert=True)
        sel.handle_alert(cancel)
        flash.assert_no_errors()
Esempio n. 13
0
        ],
        "reports_widgets_rss_feed": [
            lambda ctx: 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 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(
            "//div[contains(@class, 'dhtmlxPolyInfoBar')]"
Esempio n. 14
0
    form_buttons, Input, Table, UpDownSelect, CFMECheckbox, BootstrapTreeview)
from cfme.web_ui.form_buttons import change_stored_password
from utils import version
from utils.appliance import Navigatable
from utils.appliance.implementations.ui import navigator, CFMENavigateStep, navigate_to
from utils.log import logger
from utils.pretty import Pretty
from utils.update import Updateable


tb_select = partial(tb.select, "Configuration")
pol_btn = partial(tb.select, "Policy")

edit_tags_form = Form(
    fields=[
        ("select_tag", Select("select#tag_cat")),
        ("select_value", Select("select#tag_add"))
    ])

tag_table = Table("//div[@id='assignments_div']//table")
users_table = Table("//div[@id='records_div']//table")

group_order_selector = UpDownSelect(
    "select#seq_fields",
    "//img[@alt='Move selected fields up']",
    "//img[@alt='Move selected fields down']")


def simple_user(userid, password):
    creds = Credential(principal=userid, secret=password)
    return User(name=userid, credential=creds)
Esempio n. 15
0

cfg_btn = partial(tb.select, "Configuration")
accordion_tree = partial(accordion.tree, "Orchestration Templates")

dialog_form = Form(
    fields=[
        ('dialog_name', Input("dialog_name")),
        ('save_button', form_buttons.save)
    ])

create_template_form = Form(
    fields=[
        ('description', "textarea#description"),
        ("template_type", {
            version.LOWEST: Select("select#type"),
            '5.5': AngularSelect('type')}),
        ('content', ScriptBox(ta_locator="//div[@id='basic_info_div']/div/div"
                    "/div/div/div/div/div/div/pre/span")),
        ('template_name', Input("name")),
        ('add_button', form_buttons.add),
        ('edit_button', form_buttons.save),
    ])


def _orch_templates_create_dialog(context):
    accordion_tree('All Orchestration Templates',
        context['template_type'], context['template_name'])
    cfg_btn('Create Service Dialog from Orchestration Template')

Esempio n. 16
0
class BaseVM(Pretty, Updateable, PolicyProfileAssignable, Taggable,
             SummaryMixin, Navigatable):
    """Base VM and Template class that holds the largest common functionality between VMs,
    instances, templates and images.

    In order to inherit these, you have to implement the ``on_details`` method.
    """
    pretty_attrs = ['name', 'provider', 'template_name']

    # Forms
    edit_form = Form(fields=[
        ('custom_ident', Input("custom_1")),
        ('description_tarea', "//textarea[@id='description']"),
        ('parent_sel', {
            version.LOWEST: Select("//select[@name='chosen_parent']"),
            "5.5": AngularSelect("chosen_parent")
        }),
        ('child_sel', Select("//select[@id='kids_chosen']", multi=True)),
        ('vm_sel', Select("//select[@id='choices_chosen']", multi=True)),
        ('add_btn', "//img[@alt='Move selected VMs to left']"),
        ('remove_btn', "//img[@alt='Move selected VMs to right']"),
        ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
    ])

    ###
    # Factory class methods
    #
    @classmethod
    def factory(cls, vm_name, provider, template_name=None, template=False):
        """Factory class method that determines the correct subclass for given provider.

        For reference how does that work, refer to the entrypoints in the setup.py

        Args:
            vm_name: Name of the VM/Instance as it appears in the UI
            provider: The provider object (not the string!)
            template_name: Source template name. Useful when the VM/Instance does not exist and you
                want to create it.
            template: Whether the generated object class should be VM/Instance or a template class.
        """
        try:
            return all_types(template)[provider.type](vm_name, provider,
                                                      template_name)
        except KeyError:
            # Matching via provider type failed. Maybe we have some generic classes for infra/cloud?
            try:
                return all_types(template)[provider.category](vm_name,
                                                              provider,
                                                              template_name)
            except KeyError:
                raise UnknownProviderType(
                    'Unknown type of provider CRUD object: {}'.format(
                        provider.__class__.__name__))

    ###
    # To be set or implemented
    #
    ALL_LIST_LOCATION = None
    TO_OPEN_EDIT = None  # Name of the item in Configuration that puts you in the form
    QUADICON_TYPE = "vm"
    # Titles of the delete buttons in configuration
    REMOVE_SELECTED = {
        '5.6': 'Remove selected items',
        '5.6.2.2': 'Remove selected items from the VMDB',
        '5.7': 'Remove selected items'
    }
    REMOVE_SINGLE = {
        '5.6': 'Remove Virtual Machine',
        '5.6.2.2': 'Remove from the VMDB',
        '5.7': 'Remove Virtual Machine'
    }
    RETIRE_DATE_FMT = {
        version.LOWEST: parsetime.american_date_only_format,
        '5.7': parsetime.american_minutes_with_utc
    }
    _param_name = ParamClassName('name')

    ###
    # Shared behaviour
    #
    def __init__(self, name, provider, template_name=None, appliance=None):
        super(BaseVM, self).__init__()
        Navigatable.__init__(self, appliance=appliance)
        if type(self) in {BaseVM, VM, Template}:
            raise NotImplementedError('This class cannot be instantiated.')
        self.name = name
        self.provider = provider
        self.template_name = template_name

    ###
    # Properties
    #
    @property
    def is_vm(self):
        return not isinstance(self, _TemplateMixin)

    @property
    def quadicon_type(self):
        return self.QUADICON_TYPE

    @property
    def paged_table(self):
        _paged_table_template = '//div[@id="list_grid"]/div[@class="{}"]/table/tbody'
        return version.pick({
            version.LOWEST:
            SplitPagedTable(header_data=(_paged_table_template.format("xhdr"),
                                         1),
                            body_data=(_paged_table_template.format("objbox"),
                                       0)),
            "5.5":
            PagedTable('//table'),
        })

    ###
    # Methods
    #
    def check_compliance(self, timeout=240):
        """Initiates compliance check and waits for it to finish."""
        original_state = self.compliance_status
        cfg_btn("Refresh Relationships and Power States", invokes_alert=True)
        sel.handle_alert()
        flash.assert_no_errors()
        pol_btn("Check Compliance of Last Known Configuration",
                invokes_alert=True)
        sel.handle_alert()
        flash.assert_no_errors()
        wait_for(lambda: self.compliance_status != original_state,
                 num_sec=timeout,
                 delay=5,
                 message="compliance of {} checked".format(self.name))
        return self.compliant

    @property
    def compliance_status(self):
        """Returns the title of the compliance infoblock. The title contains datetime so it can be
        compared.

        Returns:
            :py:class:`NoneType` if no title is present (no compliance checks before), otherwise str
        """
        self.load_details(refresh=True)
        return InfoBlock("Compliance", "Status").title

    @property
    def compliant(self):
        """Check if the VM is compliant

        Returns:
            :py:class:`NoneType` if the VM was never verified, otherwise :py:class:`bool`
        """
        text = self.get_detail(properties=("Compliance",
                                           "Status")).strip().lower()
        if text == "never verified":
            return None
        elif text.startswith("non-compliant"):
            return False
        elif text.startswith("compliant"):
            return True
        else:
            raise ValueError(
                "{} is not a known state for compliance".format(text))

    def delete(self, cancel=False, from_details=False):
        """Deletes the VM/Instance from the VMDB.

        Args:
            cancel: Whether to cancel the action in the alert.
            from_details: Whether to use the details view or list view.
        """

        if from_details:
            self.load_details(refresh=True)
            cfg_btn(self.REMOVE_SINGLE, invokes_alert=True)
        else:
            self.find_quadicon(mark=True)
            cfg_btn(self.REMOVE_SELECTED, invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def exists(self):
        """Checks presence of the quadicon in the CFME."""
        try:
            self.find_quadicon()
            return True
        except VmOrInstanceNotFound:
            return False

    @property
    def is_retired(self):
        """"Check retirement status of vm"""
        self.summary.reload()
        if self.summary.lifecycle.retirement_date.text_value.lower(
        ) != 'never':
            try:
                return self.summary.lifecycle.retirement_state.text_value.lower(
                ) == 'retired'
            except AttributeError:
                return False
        else:
            return False

    def find_quadicon(self,
                      do_not_navigate=False,
                      mark=False,
                      refresh=True,
                      from_any_provider=False,
                      use_search=True):
        """Find and return a quadicon belonging to a specific vm

        Args:
            from_any_provider: Whether to look for it anywhere (root of the tree). Useful when
                looking up archived or orphaned VMs

        Returns: :py:class:`cfme.web_ui.Quadicon` instance
        Raises: VmOrInstanceNotFound
        """
        quadicon = Quadicon(self.name, self.quadicon_type)
        if not do_not_navigate:
            if from_any_provider:
                # TODO implement as navigate_to when cfme.infra.virtual_machines has destination
                navigate_to(self, 'All')
            elif self.is_vm:
                navigate_to(self, 'AllForProvider', use_resetter=False)
            else:
                navigate_to(self, 'AllForProvider', use_resetter=False)
            toolbar.select('Grid View')
        else:
            # Search requires navigation, we shouldn't use it then
            use_search = False
            if refresh:
                sel.refresh()
        if not paginator.page_controls_exist():
            if self.is_vm:
                raise VmOrInstanceNotFound("VM '{}' not found in UI!".format(
                    self.name))
            else:
                raise TemplateNotFound("Template '{}' not found in UI!".format(
                    self.name))

        paginator.results_per_page(1000)
        if use_search:
            try:
                if not search.has_quick_search_box():
                    # TODO rework search for archived/orphaned VMs
                    if self.is_vm:
                        navigate_to(self, 'AllForProvider', use_resetter=False)
                    else:
                        navigate_to(self, 'AllForProvider', use_resetter=False)
                search.normal_search(self.name)
            except Exception as e:
                logger.warning("Failed to use search: %s", str(e))
        for page in paginator.pages():
            if sel.is_displayed(quadicon, move_to=True):
                if mark:
                    sel.check(quadicon.checkbox())
                return quadicon
        else:
            raise VmOrInstanceNotFound("VM '{}' not found in UI!".format(
                self.name))

    def get_detail(self, properties=None, icon_href=False):
        """Gets details from the details infoblock

        The function first ensures that we are on the detail page for the specific VM/Instance.

        Args:
            properties: An InfoBlock title, followed by the Key name, e.g. "Relationships", "Images"

        Returns:
            A string representing the contents of the InfoBlock's value.
        """
        self.load_details(refresh=True)
        if icon_href:
            return InfoBlock.icon_href(*properties)
        else:
            return InfoBlock.text(*properties)

    def open_details(self, properties=None):
        """Clicks on details infoblock"""
        self.load_details(refresh=True)
        sel.click(InfoBlock(*properties))

    @classmethod
    def get_first_vm_title(cls, do_not_navigate=False, provider=None):
        """Get the title of first VM/Instance."""
        if not do_not_navigate:
            if provider is None:
                navigate_to(cls, 'All')
            else:
                provider.load_all_provider_vms()
        return Quadicon.get_first_quad_title()

    @property
    def last_analysed(self):
        """Returns the contents of the ``Last Analysed`` field in summary"""
        return self.get_detail(properties=('Lifecycle',
                                           'Last Analyzed')).strip()

    def load_details(self, refresh=False):
        """Navigates to an VM's details page.

        Args:
            refresh: Refreshes the VM page if already there

        Raises:
            VmOrInstanceNotFound:
                When unable to find the VM passed
        """
        navigate_to(self, 'Details', use_resetter=False)
        if refresh:
            toolbar.refresh()

    def open_edit(self):
        """Loads up the edit page of the object."""
        self.load_details(refresh=True)
        cfg_btn(self.TO_OPEN_EDIT)

    def open_timelines(self):
        """Navigates to an VM's timeline page.

        Returns:
            :py:class:`TimelinesView` object
        """
        return navigate_to(self, 'Timelines')

    def rediscover(self):
        """Deletes the VM from the provider and lets it discover again"""
        self.delete(from_details=True)
        self.wait_for_delete()
        self.provider.refresh_provider_relationships()
        self.wait_to_appear()

    def rediscover_if_analysis_data_present(self):
        """Rediscovers the object if it has some analysis data present.

        Returns:
            Boolean if the rediscovery happened.
        """
        if self.last_analysed.lower() != 'never':
            self.rediscover()
            return True
        return False

    def refresh_relationships(self, from_details=False, cancel=False):
        """Executes a refresh of relationships.

        Args:
            from_details: Whether or not to perform action from instance details page
            cancel: Whether or not to cancel the refresh relationships action
        """
        if from_details:
            self.load_details()
        else:
            self.find_quadicon(mark=True)
        cfg_btn('Refresh Relationships and Power States', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def retirement_date(self):
        """Returns the retirement date of the selected machine, or 'Never'

        Returns:
            :py:class:`str` object
        """
        return self.get_detail(properties=("Lifecycle",
                                           "Retirement Date")).strip()

    def smartstate_scan(self, cancel=False, from_details=False):
        """Initiates fleecing from the UI.

        Args:
            cancel: Whether or not to cancel the refresh relationships action
            from_details: Whether or not to perform action from instance details page
        """
        if from_details:
            self.load_details(refresh=True)
        else:
            self.find_quadicon(mark=True)
        cfg_btn('Perform SmartState Analysis', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    def wait_to_disappear(self, timeout=600, load_details=True):
        """Wait for a VM to disappear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
        """
        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=30,
                 fail_func=sel.refresh,
                 fail_condition=True,
                 message="wait for vm to not exist")

    wait_for_delete = wait_to_disappear  # An alias for more fitting verbosity

    def wait_to_appear(self, timeout=600, load_details=True):
        """Wait for a VM to appear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
            from_details: when found, should it load the vm details
        """
        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=30,
                 fail_func=sel.refresh,
                 message="wait for vm to appear")
        if load_details:
            self.load_details()

    def set_ownership(self,
                      user=None,
                      group=None,
                      click_cancel=False,
                      click_reset=False):
        """Set ownership of the VM/Instance or Template/Image"""
        sel.click(self.find_quadicon(False, False, False, use_search=False))
        cfg_btn('Set Ownership')
        if click_reset:
            action = form_buttons.reset
            msg_assert = partial(flash.assert_message_match,
                                 'All changes have been reset')
        elif click_cancel:
            action = form_buttons.cancel
            msg_assert = partial(flash.assert_success_message,
                                 'Set Ownership was cancelled by the user')
        else:
            action = form_buttons.save
            msg_assert = partial(
                flash.assert_success_message,
                'Ownership saved for selected {}'.format(self.VM_TYPE))
        fill(set_ownership_form, {
            'user_name': user,
            'group_name': group
        },
             action=action)
        msg_assert()

    def unset_ownership(self):
        """Unset ownership of the VM/Instance or Template/Image"""
        # choose the vm code comes here
        sel.click(self.find_quadicon(False, False, False))
        cfg_btn('Set Ownership')
        fill(set_ownership_form, {
            'user_name': '<No Owner>',
            'group_name': 'EvmGroup-administrator'
        },
             action=form_buttons.save)
        flash.assert_success_message('Ownership saved for selected {}'.format(
            self.VM_TYPE))
Esempio n. 17
0
from utils.update import Updateable
from utils.virtual_machines import deploy_template
from utils.wait import wait_for, TimedOutError

from . import PolicyProfileAssignable, Taggable

cfg_btn = partial(toolbar.select, "Configuration")
lcl_btn = partial(toolbar.select, "Lifecycle")
mon_btn = partial(toolbar.select, 'Monitoring')
pol_btn = partial(toolbar.select, "Policy")
pwr_btn = partial(toolbar.select, "Power")

retire_remove_button = "//span[@id='remove_button']/a/img|//a/img[contains(@src, 'clear.png')]"

set_ownership_form = Form(fields=[(
    'user_name', Select("//select[@id='user_name']")
), ('group_name',
    Select("//select[@id='group_name']")), (
        'create_button',
        form_buttons.save), (
            'reset_button',
            form_buttons.reset), ('cancel_button', form_buttons.cancel)])


class _TemplateMixin(object):
    pass


class BaseVM(Pretty, Updateable, PolicyProfileAssignable, Taggable):
    """Base VM and Template class that holds the largest common functionality between VMs,
    instances, templates and images.
Esempio n. 18
0
from utils.wait import wait_for
from utils import version
from utils.pretty import Pretty
from utils.db import cfmedb
from utils.varmeth import variable

cfg_btn = partial(tb.select, 'Configuration')

pxe_server_table_exist = Table('//div[@id="records_div"]/table/tbody/tr/td')
pxe_details_page = Region(locators=dict(
    last_refreshed=InfoBlock("Basic Information", "Last Refreshed On"),
    pxe_image_type=InfoBlock("Basic Information", "Type")))

pxe_properties_form = Form(fields=[
    ('name_text', Input('name')),
    ('log_protocol', Select("//select[@id='log_protocol']")),
    ('uri_text', Input('uri')),
    ('userid_text', Input('log_userid')),
    ('password_text', Input('log_password')),
    ('verify_text', Input('log_verify')),
    ('validate_btn', "//a[@id='val']"),
    ('access_url_text', Input('access_url')),
    ('pxe_dir_text', Input('pxe_directory')),
    ('windows_dir_text', Input('windows_images_directory')),
    ('customize_dir_text', Input('customization_directory')),
    ('pxe_menu_text', Input('pxemenu_0')),
])

pxe_image_type_form = Form(fields=[('image_type',
                                    Select("//select[@id='image_typ']"))])
Esempio n. 19
0
details_page = Region(infoblock_type='detail')

# Forms
discover_form = Form(
    fields=[('rhevm_chk', Input("discover_type_rhevm")
             ), ('vmware_chk', Input("discover_type_virtualcenter")),
            ('scvmm_chk',
             Input("discover_type_scvmm")), ('from_0', Input("from_first")),
            ('from_1', Input("from_second")), ('from_2', Input("from_third")),
            ('from_3', Input("from_fourth")), ('to_3', Input("to_fourth")),
            ('start_button', FormButton("Start the Host Discovery"))])

properties_form = Form(
    fields=[('type_select', {
        version.LOWEST: Select('select#server_emstype'),
        '5.5': AngularSelect("server_emstype")
    }), ('name_text', Input("name")), ('hostname_text', Input("hostname")),
            ('ipaddress_text', Input("ipaddress"), {
                "removed_since": "5.4.0.0.15"
            }), ('api_port', Input("port")),
            ('sec_protocol', {
                version.LOWEST: Select("select#security_protocol"),
                '5.5': AngularSelect("security_protocol")
            }), ('sec_realm', Input("realm"))])

manage_policies_tree = CheckboxTree({
    version.LOWEST: "//div[@id='treebox']/div/table",
    "5.3": "//div[@id='protect_treebox']/ul"
})
Esempio n. 20
0
template_select_form = Form(
    fields=[
        ('template_table', Table('//div[@id="prov_vm_div"]/table')),
        ('add_button', form_buttons.add),
        ('cancel_button', form_buttons.cancel)
    ]
)

# Forms
basic_info_form = Form(
    fields=[
        ('name_text', Input("name")),
        ('description_text', Input("description")),
        ('display_checkbox', Input("display")),
        ('select_catalog', Select("//select[@id='catalog_id']")),
        ('select_dialog', Select("//select[@id='dialog_id']")),
        ('select_orch_template', Select("//select[@id='template_id']")),
        ('select_provider', Select("//select[@id='manager_id']")),
        ('field_entry_point', Input("fqname")),
        ('edit_button', form_buttons.save),
        ('apply_btn', {
            version.LOWEST: '//a[@title="Apply"]',
            '5.5.0.6': '//a[normalize-space(.)="Apply"]'})
    ])

edit_tags_form = Form(
    fields=[
        ("select_tag", Select("select#tag_cat")),
        ("select_value", Select("select#tag_add"))
    ])
Esempio n. 21
0
def select(**kwargs):
    return Select(tag("select", **kwargs))
Esempio n. 22
0
order_button = {
    version.LOWEST: "//img[@title='Order this Service']",
    '5.4': "//button[@title='Order this Service']"
}
accordion_tree = partial(accordion.tree, "Service Catalogs")

# Forms
stack_form = Form(
    fields=[('timeout',
             Input("stack_timeout")), ('key_name', Input("param_KeyName")),
            ('db_user', Input("param_DBUser__protected")
             ), ('db_password', Input("param_DBPassword__protected")),
            ('db_root_password', Input("param_DBRootPassword__protected")),
            ('select_instance_type',
             Select("//select[@id='param_InstanceType']")
             ), ('stack_name', Input("stack_name"))])

menu.nav.add_branch(
    'services_catalogs', {
        'service_catalogs': [
            lambda _: accordion.click('Service Catalogs'), {
                'service_catalog': [
                    lambda ctx: accordion_tree('All Services', ctx[
                        'catalog'], ctx['catalog_item'].name), {
                            'order_service_catalog':
                            lambda _: sel.click(order_button)
                        }
                ]
            }
        ]
Esempio n. 23
0
    }
)


# I like this but it will have to go away later
def tag(tag_name, **kwargs):
    prefix = "//{}".format(tag_name)
    if kwargs:
        return prefix + "[{}]".format(
            " and ".join(["@{}='{}'".format(k, v) for k, v in kwargs.iteritems()])
        )
    else:
        return prefix

input = partial(tag, "input")
select = lambda **kwargs: Select(tag("select", **kwargs))
img = partial(tag, "img")
table = partial(tag, "table")

report_form = TabStripForm(
    # These are displayed always
    fields=[
        ("menu_name", input(id="name")),
        ("title", input(id="title")),
    ],
    tab_fields={
        "Columns": [
            ("base_report_on", select(id="chosen_model")),
            ("report_fields", MultiBoxSelect(
                select(id="available_fields"),
                select(id="selected_fields"),
Esempio n. 24
0
details_page = Region(infoblock_type='detail')

# Forms
discover_form = Form(
    fields=[
        ('username', "//*[@id='userid']"),
        ('password', "//*[@id='password']"),
        ('password_verify', "//*[@id='verify']"),
        ('start_button', "//input[@name='start']"),
        ('cancel_button', "//input[@name='cancel']"),
    ])

properties_form = Form(
    fields=[
        ('type_select', Select("//*[@id='server_emstype']")),
        ('name_text', "//*[@id='name']"),
        ('hostname_text', "//*[@id='hostname']"),
        ('ipaddress_text', "//*[@id='ipaddress']"),
        ('amazon_region_select', Select("//*[@id='hostname']")),
        ('api_port', "//*[@id='port']"),
    ])

credential_form = Form(
    fields=[
        ('default_button', "//div[@id='auth_tabs']/ul/li/a[@href='#default']"),
        ('default_principal', "//*[@id='default_userid']"),
        ('default_secret', "//*[@id='default_password']"),
        ('default_verify_secret', "//*[@id='default_verify']"),
        ('amqp_button', "//div[@id='auth_tabs']/ul/li/a[@href='#amqp']"),
        ('amqp_principal', "//*[@id='amqp_userid']"),
Esempio n. 25
0
})
dynamic_tree = Tree(
    "//div[@id='basic_info_div']//ul[@class='dynatree-container']")

template_select_form = Form(
    fields=[('template_table', Table('//div[@id="prov_vm_div"]/table')
             ), ('add_button',
                 form_buttons.add), ('cancel_button', form_buttons.cancel)])

# Forms
basic_info_form = Form(
    fields=[('name_text',
             Input("name")), (
                 'description_text',
                 Input("description")), ('display_checkbox', Input("display")),
            ('select_catalog', Select("//select[@id='catalog_id']")
             ), ('select_dialog', Select("//select[@id='dialog_id']")
                 ), ('edit_button',
                     form_buttons.save), ('field_entry_point',
                                          Input("fqname")),
            ('apply_btn', {
                version.LOWEST: '//a[@title="Apply"]',
                '5.5': '//a[normalize-space(.)="Apply"]'
            })])

detail_form = Form(fields=[('long_desc',
                            "//textarea[@id='long_description']")])


def _all_catalogitems_add_new(context):
    accordion.tree('Catalog Items', 'All Catalog Items')
Esempio n. 26
0
 def type_loc(self):
     return Select("//select[@id='var_type__{}']".format(self.seq_id))
Esempio n. 27
0
policy_page = Region(
    locators={
        'policy_tree': Tree('//div[@class="containerTableStyle"]/table')
    })

manage_policies_tree = CheckboxTree({
    version.LOWEST: "//div[@id='treebox']/div/table",
    "5.3": "//div[@id='protect_treebox']/ul"
})

# Forms
edit_form = Form(fields=[
    ('custom_ident', "//*[@id='custom_1']"),
    ('description_tarea', "//textarea[@id='description']"),
    ('parent_sel', Select("//select[@name='chosen_parent']")),
    ('child_sel', Select("//select[@id='kids_chosen']", multi=True)),
    ('vm_sel', Select("//select[@id='choices_chosen']", multi=True)),
    ('add_btn', "//img[@alt='Move selected VMs to left']"),
    ('remove_btn', "//img[@alt='Move selected VMs to right']"),
    ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
])

nav.add_branch(
    "clouds_instances", {
        "clouds_instances_by_provider": [
            lambda _: accordion.
            tree("Instances by Provider", "Instances by Provider"), {
                "clouds_instances_provider_branch": [
                    lambda ctx: visible_tree.click_path(ctx["provider_name"]),
                    {
Esempio n. 28
0
template_select_form = Form(fields=[('template_table',
                                     Table('//div[@id="pre_prov_div"]//table')
                                     ), ('cancel_button',
                                         form_buttons.cancel)])

snapshot_form = Form(
    fields=[('name', Input('name')), ('description', Input('description')),
            ('snapshot_memory',
             Input('snap_memory')), (
                 'create_button',
                 create_button), ('cancel_button', form_buttons.cancel)])

retirement_date_form = Form(
    fields=[('retirement_date_text', Calendar("miq_date_1")),
            ('retirement_warning_select',
             Select("//select[@id='retirement_warn']"))])

retire_remove_button = "//span[@id='remove_button']/a/img"

match_page = partial(match_location,
                     controller='vm_infra',
                     title='Virtual Machines')

drift_table = CheckboxTable(
    "//th[normalize-space(.)='Timestamp']/ancestor::table[1]")


class InfraGenericDetailsToolbar(View):
    reload = Button(title='Reload current display')
    configuration = Dropdown('Configuration')
    policy = Dropdown('Policy')
Esempio n. 29
0
class BaseVM(Pretty, Updateable, PolicyProfileAssignable, Taggable,
             SummaryMixin, Navigatable):
    """Base VM and Template class that holds the largest common functionality between VMs,
    instances, templates and images.

    In order to inherit these, you have to implement the ``on_details`` method.
    """
    pretty_attrs = ['name', 'provider', 'template_name']

    # Forms
    edit_form = Form(fields=[
        ('custom_ident', Input("custom_1")),
        ('description_tarea', "//textarea[@id='description']"),
        ('parent_sel', {
            version.LOWEST: Select("//select[@name='chosen_parent']"),
            "5.5": AngularSelect("chosen_parent")
        }),
        ('child_sel', Select("//select[@id='kids_chosen']", multi=True)),
        ('vm_sel', Select("//select[@id='choices_chosen']", multi=True)),
        ('add_btn', "//img[@alt='Move selected VMs to left']"),
        ('remove_btn', "//img[@alt='Move selected VMs to right']"),
        ('remove_all_btn', "//img[@alt='Move all VMs to right']"),
    ])

    ###
    # Factory class methods
    #
    @classmethod
    def factory(cls, vm_name, provider, template_name=None, template=False):
        """Factory class method that determines the correct subclass for given provider.

        For reference how does that work, refer to the entrypoints in the setup.py

        Args:
            vm_name: Name of the VM/Instance as it appears in the UI
            provider: The provider object (not the string!)
            template_name: Source template name. Useful when the VM/Instance does not exist and you
                want to create it.
            template: Whether the generated object class should be VM/Instance or a template class.
        """
        try:
            return all_types(template)[provider.type](vm_name, provider,
                                                      template_name)
        except KeyError:
            # Matching via provider type failed. Maybe we have some generic classes for infra/cloud?
            try:
                return all_types(template)[provider.category](vm_name,
                                                              provider,
                                                              template_name)
            except KeyError:
                raise UnknownProviderType(
                    'Unknown type of provider CRUD object: {}'.format(
                        provider.__class__.__name__))

    ###
    # To be set or implemented
    #
    ALL_LIST_LOCATION = None
    TO_OPEN_EDIT = None  # Name of the item in Configuration that puts you in the form
    QUADICON_TYPE = "vm"
    # Titles of the delete buttons in configuration
    REMOVE_SELECTED = {
        '5.6': 'Remove selected items',
        '5.6.2.2': 'Remove selected items from the VMDB',
        '5.7': 'Remove selected items'
    }
    REMOVE_SINGLE = {
        '5.6': 'Remove Virtual Machine',
        '5.6.2.2': 'Remove from the VMDB',
        '5.7': 'Remove Virtual Machine'
    }
    RETIRE_DATE_FMT = {
        version.LOWEST: parsetime.american_date_only_format,
        '5.7': parsetime.american_minutes_with_utc
    }
    _param_name = ParamClassName('name')

    ###
    # Shared behaviour
    #
    def __init__(self, name, provider, template_name=None, appliance=None):
        super(BaseVM, self).__init__()
        Navigatable.__init__(self, appliance=appliance)
        if type(self) in {BaseVM, VM, Template}:
            raise NotImplementedError('This class cannot be instantiated.')
        self.name = name
        self.provider = provider
        self.template_name = template_name

    ###
    # Properties
    #
    @property
    def is_vm(self):
        return not isinstance(self, _TemplateMixin)

    @property
    def quadicon_type(self):
        return self.QUADICON_TYPE

    @property
    def paged_table(self):
        _paged_table_template = '//div[@id="list_grid"]/div[@class="{}"]/table/tbody'
        return version.pick({
            version.LOWEST:
            SplitPagedTable(header_data=(_paged_table_template.format("xhdr"),
                                         1),
                            body_data=(_paged_table_template.format("objbox"),
                                       0)),
            "5.5":
            PagedTable('//table'),
        })

    ###
    # Methods
    #
    def check_compliance(self, timeout=240):
        """Initiates compliance check and waits for it to finish.

        TODO This should be refactored as it's done `Host.check_compliance`. It shouldn't return
        anything. `compliant` property should use `compliance_status`.

        """
        original_state = self.compliance_status
        cfg_btn("Refresh Relationships and Power States", invokes_alert=True)
        sel.handle_alert()
        flash.assert_no_errors()
        pol_btn("Check Compliance of Last Known Configuration",
                invokes_alert=True)
        sel.handle_alert()
        flash.assert_no_errors()
        wait_for(lambda: self.compliance_status != original_state,
                 num_sec=timeout,
                 delay=5,
                 message="compliance of {} checked".format(self.name))
        return self.compliant

    @property
    def compliance_status(self):
        """Returns the title of the compliance infoblock. The title contains datetime so it can be
        compared.

        Returns:
            :py:class:`NoneType` if no title is present (no compliance checks before), otherwise str
        """
        self.load_details(refresh=True)
        return InfoBlock("Compliance", "Status").title

    @property
    def compliant(self):
        """Check if the VM is compliant

        Returns:
            :py:class:`NoneType` if the VM was never verified, otherwise :py:class:`bool`
        """
        text = self.get_detail(properties=("Compliance",
                                           "Status")).strip().lower()
        if text == "never verified":
            return None
        elif text.startswith("non-compliant"):
            return False
        elif text.startswith("compliant"):
            return True
        else:
            raise ValueError(
                "{} is not a known state for compliance".format(text))

    @property
    def console_handle(self):
        '''
        The basic algorithm for getting the consoles window handle is to get the
        appliances window handle and then iterate through the window_handles till we find
        one that is not the appliances window handle.   Once we find this check that it has
        a canvas widget with a specific ID
        '''
        browser = self.appliance.browser.widgetastic
        appliance_handle = browser.window_handle
        cur_handles = browser.selenium.window_handles
        logger.info("Current Window Handles:  {}".format(cur_handles))

        for handle in cur_handles:
            if handle != appliance_handle:
                # FIXME: Add code to verify the tab has the correct widget
                #      for a console tab.
                return handle

    def delete(self, cancel=False, from_details=False):
        """Deletes the VM/Instance from the VMDB.

        Args:
            cancel: Whether to cancel the action in the alert.
            from_details: Whether to use the details view or list view.
        """

        if from_details:
            self.load_details(refresh=True)
            cfg_btn(self.REMOVE_SINGLE, invokes_alert=True)
        else:
            self.find_quadicon().check()
            cfg_btn(self.REMOVE_SELECTED, invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def exists(self):
        """Checks presence of the quadicon in the CFME."""
        try:
            self.find_quadicon()
            return True
        except VmOrInstanceNotFound:
            return False

    @property
    def ip_address(self):
        """Fetches IP Address of VM"""
        return self.provider.mgmt.get_ip_address(self.name)

    @property
    def is_retired(self):
        """"Check retirement status of vm"""
        self.summary.reload()
        if self.summary.lifecycle.retirement_date.text_value.lower(
        ) != 'never':
            try:
                return self.summary.lifecycle.retirement_state.text_value.lower(
                ) == 'retired'
            except AttributeError:
                return False
        else:
            return False

    def find_quadicon(self, from_any_provider=False, use_search=True):
        """Find and return a quadicon belonging to a specific vm

        Args:
            from_any_provider: Whether to look for it anywhere (root of the tree). Useful when
                looking up archived or orphaned VMs

        Returns: entity of appropriate type
        Raises: VmOrInstanceNotFound
        """
        # todo :refactor this method replace it with vm methods like get_state
        if from_any_provider:
            view = navigate_to(self, 'All')
        else:
            view = navigate_to(self, 'AllForProvider', use_resetter=False)

        if 'Grid View' != view.toolbar.view_selector.selected:
            view.toolbar.view_selector.select('Grid View')

        if use_search:
            search.normal_search(self.name)

        try:
            return view.entities.get_entity(by_name=self.name, surf_pages=True)
        except ItemNotFound:
            raise VmOrInstanceNotFound("VM '{}' not found in UI!".format(
                self.name))

    def get_detail(self, properties=None, icon_href=False):
        """Gets details from the details infoblock

        The function first ensures that we are on the detail page for the specific VM/Instance.

        Args:
            properties: An InfoBlock title, followed by the Key name, e.g. "Relationships", "Images"

        Returns:
            A string representing the contents of the InfoBlock's value.
        """
        self.load_details(refresh=True)
        if icon_href:
            return InfoBlock.icon_href(*properties)
        else:
            return InfoBlock.text(*properties)

    def open_console(self,
                     console='VM Console',
                     invokes_alert=False,
                     cancel=False):
        """
        Initiates the opening of one of the console types supported by the Access
        button.   Presently we only support VM Console, which is the HTML5 Console.
        In case of VMware provider it could be VMRC, VNC/HTML5, WebMKS, but we only
        support VNC/HTML5.
        Possible values for 'console' could be 'VM Console' and 'Web Console', but Web
        Console is not supported as well.

        Args:
            console: one of the supported console types given by the Access button.
            invokes_alert: If the particular console will invoke a CFME popup/alert
                           setting this to true will handle this.
            cancel: Allows one to cancel the operation if the popup/alert occurs.
        """
        # TODO: implement vmrc vm console
        if console not in ['VM Console']:
            raise NotImplementedError(
                'Not supported console type: {}'.format(console))

        view = navigate_to(self, 'Details')

        # Click console button given by type
        view.toolbar.access.item_select(
            console, handle_alert=None if invokes_alert is False else True)

        # Get the consoles window handle, and then create a VMConsole object, and store
        # the VMConsole object aside.
        console_handle = self.console_handle

        if console_handle is None:
            raise TypeError("Console handle should not be None")

        appliance_handle = self.appliance.browser.widgetastic.window_handle
        logger.info("Creating VMConsole:")
        logger.info("   appliance_handle: {}".format(appliance_handle))
        logger.info("     console_handle: {}".format(console_handle))
        logger.info("               name: {}".format(self.name))

        self.vm_console = VMConsole(appliance_handle=appliance_handle,
                                    console_handle=console_handle,
                                    vm=self)

    def open_details(self, properties=None):
        """Clicks on details infoblock"""
        self.load_details(refresh=True)
        sel.click(InfoBlock(*properties))

    @classmethod
    def get_first_vm(cls, provider):
        """Get first VM/Instance."""
        # todo: move this to base provider ?
        view = navigate_to(cls, 'AllForProvider', provider=provider)
        return view.entities.get_first_entity()

    @property
    def last_analysed(self):
        """Returns the contents of the ``Last Analysed`` field in summary"""
        return self.get_detail(properties=('Lifecycle',
                                           'Last Analyzed')).strip()

    def load_details(self, refresh=False):
        """Navigates to an VM's details page.

        Args:
            refresh: Refreshes the VM page if already there

        Raises:
            VmOrInstanceNotFound:
                When unable to find the VM passed
        """
        navigate_to(self, 'Details', use_resetter=False)
        if refresh:
            toolbar.refresh()
            self.browser.plugin.ensure_page_safe()

    def open_edit(self):
        """Loads up the edit page of the object."""
        self.load_details(refresh=True)
        cfg_btn(self.TO_OPEN_EDIT)

    def open_timelines(self):
        """Navigates to an VM's timeline page.

        Returns:
            :py:class:`TimelinesView` object
        """
        return navigate_to(self, 'Timelines')

    def rediscover(self):
        """Deletes the VM from the provider and lets it discover again"""
        self.delete(from_details=True)
        self.wait_for_delete()
        self.provider.refresh_provider_relationships()
        self.wait_to_appear()

    def rediscover_if_analysis_data_present(self):
        """Rediscovers the object if it has some analysis data present.

        Returns:
            Boolean if the rediscovery happened.
        """
        if self.last_analysed.lower() != 'never':
            self.rediscover()
            return True
        return False

    def refresh_relationships(self,
                              from_details=False,
                              cancel=False,
                              from_any_provider=False):
        """Executes a refresh of relationships.

        Args:
            from_details: Whether or not to perform action from instance details page
            cancel: Whether or not to cancel the refresh relationships action
        """
        if from_details:
            self.load_details()
        else:
            self.find_quadicon(from_any_provider=from_any_provider).check()
        cfg_btn('Refresh Relationships and Power States', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    @property
    def retirement_date(self):
        """Returns the retirement date of the selected machine, or 'Never'

        Returns:
            :py:class:`str` object
        """
        return self.get_detail(properties=("Lifecycle",
                                           "Retirement Date")).strip()

    def smartstate_scan(self, cancel=False, from_details=False):
        """Initiates fleecing from the UI.

        Args:
            cancel: Whether or not to cancel the refresh relationships action
            from_details: Whether or not to perform action from instance details page
        """
        if from_details:
            self.load_details(refresh=True)
        else:
            self.find_quadicon().check()
        cfg_btn('Perform SmartState Analysis', invokes_alert=True)
        sel.handle_alert(cancel=cancel)

    def wait_to_disappear(self, timeout=600, load_details=True):
        """Wait for a VM to disappear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
        """
        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=30,
                 fail_func=sel.refresh,
                 fail_condition=True,
                 message="wait for vm to not exist")

    wait_for_delete = wait_to_disappear  # An alias for more fitting verbosity

    def wait_to_appear(self, timeout=600, load_details=True):
        """Wait for a VM to appear within CFME

        Args:
            timeout: time (in seconds) to wait for it to appear
            load_details: when found, should it load the vm details
        """
        def _refresh():
            self.provider.refresh_provider_relationships()
            self.appliance.browser.widgetastic.browser.refresh(
            )  # strange because ViaUI

        wait_for(lambda: self.exists,
                 num_sec=timeout,
                 delay=5,
                 fail_func=_refresh,
                 message="wait for vm to appear")
        if load_details:
            self.load_details()

    def set_ownership(self,
                      user=None,
                      group=None,
                      click_cancel=False,
                      click_reset=False):
        """Set ownership of the VM/Instance or Template/Image"""
        self.find_quadicon(use_search=False).click()
        cfg_btn('Set Ownership')
        if click_reset:
            action = form_buttons.reset
            msg_assert = partial(flash.assert_message_match,
                                 'All changes have been reset')
        elif click_cancel:
            action = form_buttons.cancel
            msg_assert = partial(flash.assert_success_message,
                                 'Set Ownership was cancelled by the user')
        else:
            action = form_buttons.save
            msg_assert = partial(
                flash.assert_success_message,
                'Ownership saved for selected {}'.format(self.VM_TYPE))
        fill(set_ownership_form, {
            'user_name': user,
            'group_name': group
        },
             action=action)
        msg_assert()

    def unset_ownership(self):
        """Unset ownership of the VM/Instance or Template/Image"""
        # choose the vm code comes here
        self.find_quadicon(use_search=False).click()
        cfg_btn('Set Ownership')
        fill(set_ownership_form, {
            'user_name': '<No Owner>',
            'group_name': 'EvmGroup-administrator'
        },
             action=form_buttons.save)
        flash.assert_success_message('Ownership saved for selected {}'.format(
            self.VM_TYPE))
Esempio n. 30
0
provisioning_form = tabstrip.TabStripForm(
    fields=[('submit_button', submit_button),
            ('cancel_button', form_buttons.cancel)],
    tab_fields=OrderedDict([
        ('Request', [
            ('email', '//input[@name="requester__owner_email"]'),
            ('first_name', '//input[@id="requester__owner_first_name"]'),
            ('last_name', '//input[@id="requester__owner_last_name"]'),
            ('notes', '//textarea[@id="requester__request_notes"]'),
            ('manager_name', '//input[@id="requester__owner_manager"]'),
        ]),
        ('Purpose', [
            ('apply_tags', Tree('//div[@id="all_tags_treebox"]//table')),
        ]),
        ('Catalog',
         [('vm_filter', Select('//select[@id="service__vm_filter"]')),
          ('catalog_name', Table('//div[@id="prov_vm_div"]/table')),
          ('num_vms', Select('//select[@id="service__number_of_vms"]')),
          ('vm_name', '//input[@name="service__vm_name"]'),
          ('vm_description', '//textarea[@id="service__vm_description"]'),
          ('provision_type',
           Select('//select[@id="service__provision_type"]')),
          ('linked_clone', '//input[@id="service__linked_clone"]'),
          ('pxe_server', Select('//select[@id="service__pxe_server_id"]')),
          ('pxe_image', Table('//div[@id="prov_pxe_img_div"]/table')),
          ('iso_file', Table('//div[@id="prov_iso_img_div"]/table'))]),
        ('Environment', [
            ('automatic_placement',
             '//input[@id="environment__placement_auto"]'),
            ('datacenter',
             Select('//select[@id="environment__placement_dc_name"]')),