Skip to content

Commit

Permalink
Merge pull request #2177 from zenoss/feature/feature/ZEN-26894-fix-pr…
Browse files Browse the repository at this point in the history
…oduction-state-sort-error

ZEN-26894 fix production state sort error
  • Loading branch information
jonathan borden committed Mar 21, 2017
2 parents 8a2f04f + 1c6cb0f commit 7dd69a3
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 13 deletions.
4 changes: 2 additions & 2 deletions Products/ZenWidgets/browser/Portlets.py
Expand Up @@ -19,7 +19,7 @@
from Products.ZenEvents.HeartbeatUtils import getHeartbeatObjects
from zenoss.protocols.services import ServiceException
from zenoss.protocols.services.zep import ZepConnectionError
from Products.ZenUtils.guid.interfaces import IGUIDManager
from Products.ZenUtils.guid.interfaces import IGUIDManager, IGlobalIdentifier
from Products.ZenUtils.productionstate.interfaces import IProdStateManager
from Products.ZenUtils.jsonutils import json
from Products.ZenUtils.Utils import nocache, formreq, extractPostContent
Expand Down Expand Up @@ -105,7 +105,7 @@ def getProdStateInt(prodStateString):
objects = catalog.evalAdvancedQuery(query, ((orderby, orderdir),))

psManager = IProdStateManager(self.context)
results = (x for x in objects if psManager.getProductionStateFromGUID(x.uuid) in numericProdStates)
results = (x for x in objects if psManager.getProductionStateFromGUID(IGlobalIdentifier(x).getGUID()) in numericProdStates)
devs = (x.getObject() for x in results)
mydict = {'columns':['Device', 'Prod State'], 'data':[]}
for dev in devs:
Expand Down
13 changes: 6 additions & 7 deletions Products/Zuul/facades/__init__.py
Expand Up @@ -29,6 +29,7 @@
from Products.ZenModel.DeviceOrganizer import DeviceOrganizer
from Products.ZenModel.ComponentOrganizer import ComponentOrganizer
from Products.AdvancedQuery import MatchRegexp, And, Or, Eq, Between, Generic
from Products.ZenUtils.guid.interfaces import IGlobalIdentifier
from Products.Zuul.interfaces import IFacade, ITreeNode
from Products.Zuul.interfaces import (
ITreeFacade, IInfo, ICatalogTool, IOrganizerInfo
Expand Down Expand Up @@ -198,7 +199,7 @@ def getDeviceBrains(self, uid=None, start=0, limit=50, sort='name',

if sort == "productionState":
useProdStates = True
orderby = None
orderby = 'name'
startp = 0
limitp = None

Expand All @@ -208,7 +209,6 @@ def getDeviceBrains(self, uid=None, start=0, limit=50, sort='name',
startp = 0
limitp = None


catbrains = cat.search(
'Products.ZenModel.Device.Device', start=startp,
limit=limitp, orderby=orderby, reverse=reverse,
Expand All @@ -219,7 +219,7 @@ def getDeviceBrains(self, uid=None, start=0, limit=50, sort='name',
psManager = IProdStateManager(self._dmd)
# Filter by production state
if prodStates:
psFilteredbrains = [brain for brain in catbrains if psManager.getProductionStateFromGUID(brain.uuid) in prodStates]
psFilteredbrains = [b for b in catbrains if psManager.getProductionStateFromGUID(IGlobalIdentifier(b).getGUID()) in prodStates]
totalCount = len(psFilteredbrains)
hash_ = str(totalCount)

Expand All @@ -245,15 +245,14 @@ def mergeBuckets(sortedkeys, buckets):
for ps in productionStates:
prodStateBuckets[ps] = []

for brain in psFilteredbrains:
prodState = psManager.getProductionStateFromGUID(brain.uuid)
prodStateBuckets[prodState].append(brain)
for b in psFilteredbrains:
prodState = psManager.getProductionStateFromGUID(IGlobalIdentifier(b).getGUID())
prodStateBuckets[prodState].append(b)

sortedBrains = (brain for brain in mergeBuckets(productionStates, prodStateBuckets))
else:
sortedBrains = psFilteredbrains


# Pick out the correct range and build the SearchResults object
start = max(start, 0)
if limit is None:
Expand Down
83 changes: 79 additions & 4 deletions Products/Zuul/tests/test_devicefacade.py
Expand Up @@ -9,8 +9,6 @@


import unittest
import zope.component
from Products.Zuul.catalog.interfaces import IIndexingEvent
from zope.interface.verify import verifyClass
from zope.event import notify
from Products import Zuul
Expand Down Expand Up @@ -80,7 +78,7 @@ def test_removeDeviceFromSingleGroup(self):
test_device.setGroups(groupNames)

groups = test_device.groups()

# verify all our groups are there before removing one
self.assertTrue(red_org in groups)
self.assertTrue(orange_org in groups)
Expand Down Expand Up @@ -144,7 +142,6 @@ def test_deviceSearchParams(self):
self.assertEquals(1, results.total)

def test_deviceSearchByProdState(self):
from Products.ZenModel.ZDeviceLoader import JobDeviceLoader
devMaintenance = self.dmd.Devices.createInstance('devMaintenance')
devProduction = self.dmd.Devices.createInstance('devProduction')
devMaintenance.setProdState(400)
Expand Down Expand Up @@ -177,6 +174,84 @@ def test_deviceSortByProdState(self):
self.assertEquals(resultIter.next().getObject().getProductionState(), 1000)
self.assertEquals(resultIter.next().getObject().getProductionState(), 400)

def test_deviceSortByNonIndexedFieldWithProdStateFilterReturnsCorrectDevices(self):
# This test specifically verifies the fix for ZEN-26901 sorting by a non-indexed
# field while filtering on productionState caused a ProdStateNotSetError.
devMaintenance = self.dmd.Devices.createInstance('devMaintenance')
devMaintenance.setPerformanceMonitor('localhost')
devMaintenance.setProdState(400)

devProduction = self.dmd.Devices.createInstance('devProduction')
devProduction.setPerformanceMonitor('localhost')
devProduction.setProdState(1000)

# sort by collector (non-indexed) with productionState filter
results = self.facade.getDeviceBrains(uid="/zport/dmd/Devices", sort='collector', params=dict(productionState=[400, 1000]))
resultIter = iter(results)
self.assertEquals(2, results.total)
device = resultIter.next()
self.assertEquals(device.getProductionState(), 400)
self.assertEquals(device.getPerformanceServer().id, 'localhost')
device = resultIter.next()
self.assertEquals(device.getProductionState(), 1000)
self.assertEquals(device.getPerformanceServer().id, 'localhost')

def test_deviceSortByIndexedFieldWithProdStateFilterReturnsCorrectDevices(self):
devMaintenance = self.dmd.Devices.createInstance('devMaintenance')
devMaintenance.setProdState(400)

devProduction = self.dmd.Devices.createInstance('devProduction')
devProduction.setProdState(1000)

# sort by name (indexed) with productionState filter
results = self.facade.getDeviceBrains(uid="/zport/dmd/Devices", sort='name', params=dict(productionState=[400, 1000]))
resultIter = iter(results)
self.assertEquals(2, results.total)
device = resultIter.next()
self.assertEquals(device.getObject().getProductionState(), 400)
device = resultIter.next()
self.assertEquals(device.getObject().getProductionState(), 1000)

def test_deviceSortByProdStateWithIndexedFieldFilterReturnsCorrectDevices(self):
# This test specifically verifies the fix for ZEN-26901 sorting productionState
# while filtering on an indexed field caused a ProdStateNotSetError.
devMaintenance = self.dmd.Devices.createInstance('devMaintenance')
devMaintenance.setProdState(400)

devProduction = self.dmd.Devices.createInstance('devProduction')
devProduction.setProdState(1000)

# sort by productionState with name (indexed) filter
results = self.facade.getDeviceBrains(uid="/zport/dmd/Devices", sort="productionState", params=dict(name="dev"))
resultIter = iter(results)
self.assertEquals(2, results.total)
device = resultIter.next()
self.assertEquals(device.getObject().getProductionState(), 400)
self.assertEquals(device.getObject().getDeviceName(), 'devMaintenance')
device = resultIter.next()
self.assertEquals(device.getObject().getProductionState(), 1000)
self.assertEquals(device.getObject().getDeviceName(), 'devProduction')

def test_deviceSortByProdStateWithNonIndexedFieldFilterReturnsCorrectDevices(self):
devMaintenance = self.dmd.Devices.createInstance('devMaintenance')
devMaintenance.setPerformanceMonitor("localhost")
devMaintenance.setProdState(400)

devProduction = self.dmd.Devices.createInstance('devProduction')
devProduction.setPerformanceMonitor("localhost")
devProduction.setProdState(1000)

# sort by productionState with collector (non-indexed) filter
results = self.facade.getDeviceBrains(uid="/zport/dmd/Devices", sort='productionState', params=dict(collector="local"))
resultIter = iter(results)
self.assertEquals(2, results.total)
device = resultIter.next()
self.assertEquals(device.getProductionState(), 400)
self.assertEquals(device.getPerformanceServer().id, 'localhost')
device = resultIter.next()
self.assertEquals(device.getProductionState(), 1000)
self.assertEquals(device.getPerformanceServer().id, 'localhost')

def test_setProductionState(self):
dev = self.dmd.Devices.createInstance('dev')
dev2 = self.dmd.Devices.createInstance('dev2')
Expand Down

0 comments on commit 7dd69a3

Please sign in to comment.