# -*- coding: utf-8 -*-
import attr
from navmazing import NavigateToSibling, NavigateToAttribute
from widgetastic_patternfly import Button, Dropdown
from widgetastic.widget import View, Text, NoSuchElementException
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,
BreadCrumb,
ItemsToolBarViewSelector,
ManageIQTree,
SummaryTable
)
[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 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)
@attr.s
[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 self.name 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')
view.toolbar.view_selector.select("List View")
for item in view.entities.elements.read():
if self.name 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(view.entities.properties.get_text_of('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
)
@attr.s
[docs]class VolumeSnapshotCollection(BaseCollection):
"""Collection object for :py:class:`cfme.storage.volume_snapshots.VolumeSnapshot`"""
ENTITY = VolumeSnapshot
[docs] def all(self):
"""returning all Snapshot objects for respective storage manager type"""
view = navigate_to(self, 'All')
view.toolbar.view_selector.select("List View")
snapshots = []
try:
if 'provider' in self.filters:
for item in view.entities.elements.read():
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 view.entities.elements.read():
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):
self.prerequisite_view.navigation.select('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(name=self.obj.name,
surf_pages=True).click()
except ItemNotFound:
raise SnapshotNotFoundError('Could not locate volume snapshot {}'.format(self.obj.name))
@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')