Source code for

# -*- coding: utf-8 -*-
import attr
from navmazing import NavigateToSibling, NavigateToAttribute
from widgetastic.widget import View, Text, NoSuchElementException
from widgetastic_patternfly import BreadCrumb, Button, Dropdown

from cfme.base.ui import BaseLoggedInPage
from cfme.common import TagPageView, Taggable
from cfme.exceptions import SnapshotNotFoundError, ItemNotFound
from cfme.modeling.base import BaseCollection, BaseEntity
from cfme.utils.appliance.implementations.ui import CFMENavigateStep, navigator, navigate_to
from cfme.utils.log import logger
from cfme.utils.providers import get_crud_by_name
from cfme.utils.wait import wait_for
from widgetastic_manageiq import (
    Accordion, BaseEntitiesView, ItemsToolBarViewSelector, ManageIQTree, SummaryTable)

[docs]class VolumeSnapshotToolbar(View): """The toolbar on the Volume Snapshot page""" policy = Dropdown('Policy') download = Dropdown('Download') view_selector = View.nested(ItemsToolBarViewSelector)
[docs]class VolumeSnapshotDetailsToolbar(View): """The toolbar on the Volume Snapshot detail page""" configuration = Dropdown('Configuration') policy = Dropdown('Policy') download = Button('Download summary in PDF format')
[docs]class VolumeSnapshotDetailsEntities(View): """The entities on the Volume Snapshot detail page""" breadcrumb = BreadCrumb() title = Text('.//div[@id="center_div" or @id="main-content"]//h1') properties = SummaryTable('Properties') relationships = SummaryTable('Relationships') smart_management = SummaryTable('Smart Management')
[docs]class VolumeSnapshotDetailSidebar(View): """The accordion on the Volume Snapshot details page""" @View.nested class properties(Accordion): # noqa tree = ManageIQTree() @View.nested class relationships(Accordion): # noqa tree = ManageIQTree()
[docs]class VolumeSnapshotView(BaseLoggedInPage): """A base view for all the Volume Snapshot pages""" @property def in_volume_snapshots(self): return ( self.logged_in_as_current_user and self.navigation.currently_selected == ['Storage', 'Block Storage', 'Volume Snapshots'] ) @property def is_displayed(self): return self.in_volume_snapshots
[docs]class VolumeSnapshotAllView(VolumeSnapshotView): """The all Volume Snapshot page""" toolbar = View.nested(VolumeSnapshotToolbar) including_entities = View.include(BaseEntitiesView, use_parent=True) @property def is_displayed(self): return ( self.in_volume_snapshots and self.entities.title.text == 'Cloud Volume Snapshots')
[docs]class VolumeSnapshotDetailsView(VolumeSnapshotView): """The detail Volume Snapshot page""" @property def is_displayed(self): expected_title = '{} (Summary)'.format(self.context['object'].name) return ( self.in_volume_snapshots and self.entities.title.text == expected_title and self.entities.breadcrumb.active_location == expected_title) toolbar = View.nested(VolumeSnapshotDetailsToolbar) sidebar = View.nested(VolumeSnapshotDetailSidebar) entities = View.nested(VolumeSnapshotDetailsEntities)
[docs]class VolumeSnapshot(BaseEntity, Taggable): """ Model of an Storage Volume Snapshots in cfme Args: name: name of the snapshot provider: provider """ name = attr.ib() provider = attr.ib()
[docs] def refresh(self): self.provider.refresh_provider_relationships() self.browser.refresh()
@property def exists(self): """ check for snapshot exist on UI. Returns: :py:class:`bool` """ view = navigate_to(self.parent, 'All') return in view.entities.all_entity_names @property def status(self): """ status of cloud volume snapshot. Returns: :py:class:`str` Status of volume snapshot. """ view = navigate_to(self.parent, 'All')"List View") for item in if in item['Name']: return str(item['Status']) @property def size(self): """ size of cloud volume snapshot. Returns: :py:class:`int` size of volume snapshot in GB. """ view = navigate_to(self, 'Details') return int('Size').split()[0]) @property def volume_name(self): """ volume name of snapshot. Returns: :py:class:`str` respective volume name. """ view = navigate_to(self, 'Details') return view.entities.relationships.get_text_of('Cloud Volume') @property def tenant_name(self): """ Tenant name of snapshot. Returns: :py:class:`str` respective tenant name for snapshot. """ view = navigate_to(self, 'Details') return view.entities.relationships.get_text_of('Cloud Tenants')
[docs] def delete(self, wait=True): """Delete snapshot """ view = navigate_to(self, 'Details') view.toolbar.configuration.item_select('Delete Cloud Volume Snapshot') view.flash.assert_success_message('Delete initiated for 1 Cloud Volume Snapshot.') if wait: wait_for( lambda: not self.exists, message="Wait snapshot to disappear", delay=20, timeout=800, fail_func=self.refresh )
[docs]class VolumeSnapshotCollection(BaseCollection): """Collection object for :py:class:``""" ENTITY = VolumeSnapshot
[docs] def all(self): """returning all Snapshot objects for respective storage manager type""" view = navigate_to(self, 'All')"List View") snapshots = [] try: if 'provider' in self.filters: for item in if self.filters.get('provider').name in item['Storage Manager']: snapshots.append(self.instantiate(name=item['Name'], provider=self.filters.get('provider'))) else: for item in provider_name = item['Storage Manager'].split()[0] provider = get_crud_by_name(provider_name) snapshots.append(self.instantiate(name=item['Name'], provider=provider)) except NoSuchElementException: if snapshots: logger.error('VolumeSnapshotCollection: ' 'NoSuchElementException in the middle of entities read') else: logger.warning('The snapshot table is probably not present or empty') return snapshots
@navigator.register(VolumeSnapshotCollection, 'All')
[docs]class All(CFMENavigateStep): VIEW = VolumeSnapshotAllView prerequisite = NavigateToAttribute('appliance.server', 'LoggedIn')
[docs] def step(self):'Storage', 'Block Storage', 'Volume Snapshots')
@navigator.register(VolumeSnapshot, 'Details')
[docs]class Details(CFMENavigateStep): VIEW = VolumeSnapshotDetailsView prerequisite = NavigateToAttribute('parent', 'All')
[docs] def step(self, *args, **kwargs): try: self.prerequisite_view.entities.get_entity(, surf_pages=True).click() except ItemNotFound: raise SnapshotNotFoundError('Could not locate volume snapshot {}'.format(
@navigator.register(VolumeSnapshot, 'EditTagsFromDetails')
[docs]class SnapshotDetailEditTag(CFMENavigateStep): """ This navigation destination help to Taggable""" VIEW = TagPageView prerequisite = NavigateToSibling('Details')
[docs] def step(self, *args, **kwargs): self.prerequisite_view.toolbar.policy.item_select('Edit Tags')