Package Products :: Package Zuul :: Package routers :: Module device
[hide private]
[frames] | no frames]

Source Code for Module Products.Zuul.routers.device

   1  ############################################################################## 
   2  # 
   3  # Copyright (C) Zenoss, Inc. 2009-2013, all rights reserved. 
   4  # 
   5  # This content is made available according to terms specified in 
   6  # License.zenoss under the directory where your Zenoss product is installed. 
   7  # 
   8  ############################################################################## 
   9   
  10   
  11  """ 
  12  Operations for Device Organizers and Devices. 
  13   
  14  Available at:  /zport/dmd/device_router 
  15  """ 
  16  import logging 
  17  from itertools import islice 
  18  from AccessControl import Unauthorized 
  19  from Products.ZenUtils.Ext import DirectResponse 
  20  from Products.ZenUtils.Utils import getDisplayType 
  21  from Products.ZenUtils.jsonutils import unjson 
  22  from Products import Zuul 
  23  from Products.ZenModel.Device import Device 
  24  from Products.ZenModel.ZenossSecurity import ZEN_CHANGE_DEVICE_PRODSTATE, ZEN_MANAGE_DMD, \ 
  25      ZEN_ADMIN_DEVICE, ZEN_MANAGE_DEVICE, ZEN_DELETE_DEVICE 
  26  from Products.Zuul import filterUidsByPermission 
  27  from Products.Zuul.routers import TreeRouter 
  28  from Products.Zuul.exceptions import DatapointNameConfict 
  29  from Products.Zuul.catalog.events import IndexingEvent 
  30  from Products.Zuul.form.interfaces import IFormBuilder 
  31  from Products.Zuul.decorators import require, contextRequire, serviceConnectionError 
  32  from Products.ZenUtils.guid.interfaces import IGlobalIdentifier, IGUIDManager 
  33  from Products.ZenMessaging.audit import audit 
  34  from zope.event import notify 
  35   
  36  log = logging.getLogger('zen.Zuul') 
37 38 -class DeviceRouter(TreeRouter):
39 """ 40 A JSON/ExtDirect interface to operations on devices 41 """ 42 43 @serviceConnectionError 44 @contextRequire("Manage DMD", 'contextUid')
45 - def addDeviceClassNode(self, type, contextUid, id, description=None, connectionInfo=None):
46 """ 47 Adds a new device class organizer specified by the parameter id to 48 the parent organizer specified by contextUid. 49 50 contextUid must be a path to a DeviceClass. 51 52 @type type: string 53 @param type: Node type (always 'organizer' in this case) 54 @type contextUid: string 55 @param contextUid: Path to the location organizer that will 56 be the new node's parent (ex. /zport/dmd/Devices/) 57 @type id: string 58 @param id: The identifier of the new node 59 @type description: string 60 @param description: (optional) Describes the new device class 61 @type connectionInfo: list 62 @param connectionInfo: (optional) List of zproperties that constitute credentials for this device classs 63 @rtype: dictionary 64 @return: B{Properties}: 65 - success: (bool) Success of node creation 66 - nodeConfig: (dictionary) The new device class's properties 67 """ 68 facade = self._getFacade() 69 organizer = facade.addDeviceClass(contextUid, 70 id, 71 description, 72 connectionInfo) 73 uid = organizer.uid 74 75 treeNode = facade.getTree(uid) 76 audit('UI.DeviceClass.Add', uid, description=description, connectionInfo=connectionInfo) 77 return DirectResponse.succeed("Device Class Added", nodeConfig=Zuul.marshal(treeNode))
78 79 80 @serviceConnectionError 81 @contextRequire("Manage DMD", 'contextUid')
82 - def addLocationNode(self, type, contextUid, id, 83 description=None, address=None):
84 """ 85 Adds a new location organizer specified by the parameter id to 86 the parent organizer specified by contextUid. 87 88 contextUid must be a path to a Location. 89 90 @type type: string 91 @param type: Node type (always 'organizer' in this case) 92 @type contextUid: string 93 @param contextUid: Path to the location organizer that will 94 be the new node's parent (ex. /zport/dmd/Devices/Locations) 95 @type id: string 96 @param id: The identifier of the new node 97 @type description: string 98 @param description: (optional) Describes the new location 99 @type address: string 100 @param address: (optional) Physical address of the new location 101 @rtype: dictionary 102 @return: B{Properties}: 103 - success: (bool) Success of node creation 104 - nodeConfig: (dictionary) The new location's properties 105 """ 106 facade = self._getFacade() 107 organizer = facade.addLocationOrganizer(contextUid, 108 id, 109 description, 110 address) 111 uid = organizer.uid 112 113 treeNode = facade.getTree(uid) 114 audit('UI.Location.Add', uid, description=description, address=address) 115 return DirectResponse.succeed("Location added", nodeConfig=Zuul.marshal(treeNode))
116
117 - def _getFacade(self):
118 return Zuul.getFacade('device', self.context)
119 120 @serviceConnectionError
121 - def getTree(self, id):
122 """ 123 Returns the tree structure of an organizer hierarchy where 124 the root node is the organizer identified by the id parameter. 125 126 @type id: string 127 @param id: Id of the root node of the tree to be returned 128 @rtype: [dictionary] 129 @return: Object representing the tree 130 """ 131 facade = self._getFacade() 132 tree = facade.getTree(id) 133 data = Zuul.marshal(tree) 134 return [data]
135 136 @serviceConnectionError
137 - def getComponents(self, uid=None, meta_type=None, keys=None, start=0, 138 limit=50, page=0, sort='name', dir='ASC', name=None):
139 """ 140 Retrieves all of the components at a given UID. This method 141 allows for pagination. 142 143 @type uid: string 144 @param uid: Unique identifier of the device whose components are 145 being retrieved 146 @type meta_type: string 147 @param meta_type: (optional) The meta type of the components to be 148 retrieved (default: None) 149 @type keys: list 150 @param keys: (optional) List of keys to include in the returned 151 dictionary. If None then all keys will be returned 152 (default: None) 153 @type start: integer 154 @param start: (optional) Offset to return the results from; used in 155 pagination (default: 0) 156 @type limit: integer 157 @param limit: (optional) Number of items to return; used in pagination 158 (default: 50) 159 @type sort: string 160 @param sort: (optional) Key on which to sort the return results; 161 (default: 'name') 162 @type dir: string 163 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 164 (default: 'ASC') 165 @type name: regex 166 @param name: (optional) Used to filter the results (default: None) 167 @rtype: DirectResponse 168 @return: B{Properties}: 169 - data: (dictionary) The components returned 170 - totalCount: (integer) Number of items returned 171 - hash: (string) Hashcheck of the current component state (to check 172 whether components have changed since last query) 173 """ 174 facade = self._getFacade() 175 if name: 176 # Load every component if we have a filter 177 limit = None 178 comps = facade.getComponents(uid, meta_type=meta_type, start=start, 179 limit=limit, sort=sort, dir=dir, name=name, keys=keys) 180 total = comps.total 181 hash = comps.hash_ 182 183 data = Zuul.marshal(comps, keys=keys) 184 return DirectResponse(data=data, totalCount=total, 185 hash=hash)
186
187 - def getComponentTree(self, uid=None, id=None, sorting_dict=None):
188 """ 189 Retrieves all of the components set up to be used in a 190 tree. 191 192 @type uid: string 193 @param uid: Unique identifier of the root of the tree to retrieve 194 @type id: string 195 @param id: not used 196 @rtype: [dictionary] 197 @return: Component properties in tree form 198 """ 199 if id: 200 uid = id 201 facade = self._getFacade() 202 data = facade.getComponentTree(uid) 203 sevs = [c[0].lower() for c in 204 self.context.ZenEventManager.severityConversions] 205 data.sort(cmp=lambda a, b: cmp(sevs.index(a['severity']), 206 sevs.index(b['severity']))) 207 result = [] 208 for datum in data: 209 result.append(dict( 210 id=datum['type'], 211 path='Components/%s' % datum['type'], 212 text={ 213 'text': datum['type'], 214 'count': datum['count'], 215 'description': 'components'}, 216 iconCls='tree-severity-icon-small-' + datum['severity'], 217 leaf=True)) 218 if sorting_dict: 219 sorting_keys_list = [key for key in sorting_dict.iterkeys()] 220 def cmp_items(first, second): 221 # Resolving keys from a dictionary of given names convention 222 x = str(first['text']['text']) 223 y = str(second['text']['text']) 224 if x in sorting_keys_list: 225 x = sorting_dict[x][0] 226 if y in sorting_keys_list: 227 y = sorting_dict[y][0] 228 if x < y: 229 return -1 230 elif x > y: 231 return 1 232 else: 233 return 0
234 result.sort(cmp=cmp_items) 235 return result
236
237 - def findComponentIndex(self, componentUid, uid=None, meta_type=None, 238 sort='name', dir='ASC', name=None, **kwargs):
239 """ 240 Given a component uid and the component search criteria, this retrieves 241 the position of the component in the results. 242 243 @type componentUid: string 244 @param componentUid: Unique identifier of the component whose index 245 to return 246 @type uid: string 247 @param uid: Unique identifier of the device queried for components 248 @type meta_type: string 249 @param meta_type: (optional) The meta type of the components to retrieve 250 (default: None) 251 @type sort: string 252 @param sort: (optional) Key on which to sort the return results (default: 253 'name') 254 @type dir: string 255 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 256 (default: 'ASC') 257 @type name: regex 258 @param name: (optional) Used to filter the results (default: None) 259 @rtype: DirectResponse 260 @return: B{Properties}: 261 - index: (integer) Index of the component 262 """ 263 facade = self._getFacade() 264 i = facade.findComponentIndex(componentUid, uid, 265 meta_type, sort, dir, name) 266 return DirectResponse(index=i)
267 268 @serviceConnectionError
269 - def getForm(self, uid):
270 """ 271 Given an object identifier, this returns all of the editable fields 272 on that object as well as their ExtJs xtype that one would 273 use on a client side form. 274 275 @type uid: string 276 @param uid: Unique identifier of an object 277 @rtype: DirectResponse 278 @return: B{Properties} 279 - form: (dictionary) form fields for the object 280 """ 281 info = self._getFacade().getInfo(uid) 282 form = IFormBuilder(info).render(fieldsets=False) 283 form = Zuul.marshal(form) 284 return DirectResponse(form=form)
285 286 @serviceConnectionError
287 - def getInfo(self, uid, keys=None):
288 """ 289 Get the properties of a device or device organizer 290 291 @type uid: string 292 @param uid: Unique identifier of an object 293 @type keys: list 294 @param keys: (optional) List of keys to include in the returned 295 dictionary. If None then all keys will be returned 296 (default: None) 297 @rtype: DirectResponse 298 @return: B{Properties} 299 - data: (dictionary) Object properties 300 - disabled: (bool) If current user doesn't have permission to use setInfo 301 """ 302 facade = self._getFacade() 303 process = facade.getInfo(uid) 304 data = Zuul.marshal(process, keys) 305 disabled = not Zuul.checkPermission('Manage DMD', self.context) 306 return DirectResponse(data=data, disabled=disabled)
307 308 @serviceConnectionError
309 - def setInfo(self, **data):
310 """ 311 Set attributes on a device or device organizer. 312 This method accepts any keyword argument for the property that you wish 313 to set. The only required property is "uid". 314 315 @type uid: string 316 @keyword uid: Unique identifier of an object 317 @rtype: DirectResponse 318 """ 319 facade = self._getFacade() 320 if not Zuul.checkPermission('Manage DMD', self.context): 321 raise Exception('You do not have permission to save changes.') 322 the_uid = data['uid'] # gets deleted 323 process = facade.getInfo(the_uid) 324 oldData = self._getInfoData(process, data.keys()) 325 Zuul.unmarshal(data, process) 326 newData = self._getInfoData(process, data.keys()) 327 # reindex the object if necessary 328 if hasattr(process._object, 'index_object'): 329 process._object.index_object() 330 331 # Ex: ('UI.Device.Edit', uid, data_={'productionState': 'High'}) 332 # Ex: ('UI.Location.Edit', uid, description='Blah', old_description='Foo') 333 if 'name' in oldData: 334 oldData['device_name'] = oldData['name'] # we call it this now 335 del oldData['name'] 336 if 'name' in newData: 337 del newData['name'] # it gets printed automatically 338 if isinstance(process._object, Device): 339 # ZEN-2837, ZEN-247: Audit names instead of numbers 340 dmd = self.context 341 if 'productionState' in oldData: 342 oldData['productionState'] = dmd.convertProdState(oldData['productionState']) 343 if 'productionState' in newData: 344 newData['productionState'] = dmd.convertProdState(newData['productionState']) 345 if 'priority' in oldData: 346 oldData['priority'] = dmd.convertPriority(oldData['priority']) 347 if 'priority' in newData: 348 newData['priority'] = dmd.convertPriority(newData['priority']) 349 audit(['UI', getDisplayType(process._object), 'Edit'], the_uid, 350 data_=newData, oldData_=oldData, skipFields_='uid') 351 return DirectResponse.succeed()
352
353 - def _getInfoData(self, info, keys):
354 # TODO: generalize this code for all object types, if possible. 355 values = {} 356 for key in keys: 357 val = getattr(info, key, None) 358 if val is not None: 359 values[key] = str(val) # unmutable copy 360 return values
361 362 @require('Manage Device')
363 - def setProductInfo(self, uid, **data):
364 """ 365 Sets the ProductInfo on a device. This method has the following valid 366 keyword arguments: 367 368 @type uid: string 369 @keyword uid: Unique identifier of a device 370 @type hwManufacturer: string 371 @keyword hwManufacturer: Hardware manufacturer 372 @type hwProductName: string 373 @keyword hwProductName: Hardware product name 374 @type osManufacturer: string 375 @keyword osManufacturer: Operating system manufacturer 376 @type osProductName: string 377 @keyword osProductName: Operating system product name 378 @rtype: DirectResponse 379 """ 380 facade = self._getFacade() 381 facade.setProductInfo(uid, **data) 382 audit('UI.Device.Edit', uid, data_=data) 383 return DirectResponse()
384
385 - def getDeviceUuidsByName(self, query="", start=0, limit=25, page=1, uuid=None):
386 """ 387 Retrieves a list of device uuids. For use in combos. 388 If uuid is set, ensures that it is included in the returned list. 389 """ 390 facade = self._getFacade() 391 devices = facade.getDevices(params={'name':query}) # TODO: pass start=start, limit=limit 392 result = [{'name':dev.name, 393 'uuid':IGlobalIdentifier(dev._object).getGUID()} 394 for dev in devices] 395 396 if uuid and uuid not in (device['uuid'] for device in result): 397 guidManager = IGUIDManager(self.context.dmd) 398 device = guidManager.getObject(uuid) 399 if device: 400 result.append({'name':device.name(), 'uuid':uuid}) 401 402 return DirectResponse.succeed(data=result)
403
404 - def getDeviceUids(self, uid):
405 """ 406 Return a list of device uids underneath an organizer. This includes 407 all the devices belonging to an child organizers. 408 409 @type uid: string 410 @param uid: Unique identifier of the organizer to get devices from 411 @rtype: DirectResponse 412 @return: B{Properties}: 413 - devices: (list) device uids 414 """ 415 facade = self._getFacade() 416 uids = facade.getDeviceUids(uid) 417 return DirectResponse.succeed(devices=uids)
418 419 @serviceConnectionError
420 - def getDevices(self, uid=None, start=0, params=None, limit=50, sort='name', 421 page=None, 422 dir='ASC', keys=None):
423 """ 424 Retrieves a list of devices. This method supports pagination. 425 426 @type uid: string 427 @param uid: Unique identifier of the organizer to get devices from 428 @type start: integer 429 @param start: (optional) Offset to return the results from; used in 430 pagination (default: 0) 431 @type params: dictionary 432 @param params: (optional) Key-value pair of filters for this search. 433 Can be one of the following: name, ipAddress, 434 deviceClass, or productionState (default: None) 435 @type limit: integer 436 @param limit: (optional) Number of items to return; used in pagination 437 (default: 50) 438 @type sort: string 439 @param sort: (optional) Key on which to sort the return results (default: 440 'name') 441 @type dir: string 442 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 443 (default: 'ASC') 444 @rtype: DirectResponse 445 @return: B{Properties}: 446 - devices: (list) Dictionaries of device properties 447 - totalCount: (integer) Number of devices returned 448 - hash: (string) Hashcheck of the current device state (to check 449 whether devices have changed since last query) 450 """ 451 facade = self._getFacade() 452 if isinstance(params, basestring): 453 params = unjson(params) 454 455 devices = facade.getDevices(uid, start, limit, sort, dir, params) 456 allKeys = ['name', 'ipAddress', 'productionState', 'events', 457 'ipAddressString', 'serialNumber', 'hwManufacturer', 458 'hwModel', 'osModel', 'osManufacturer', 'collector', 459 'priority', 'systems', 'groups', 'location', 460 'pythonClass', 'tagNumber'] 461 usedKeys = keys or allKeys 462 if not 'uid' in usedKeys: 463 usedKeys.append('uid') 464 465 data = Zuul.marshal(devices.results, usedKeys) 466 467 return DirectResponse(devices=data, totalCount=devices.total, 468 hash=devices.hash_)
469
470 - def renameDevice(self, uid, newId):
471 """ 472 Set the device specified by the uid,"uid" to have the 473 the id "newId" 474 This will raise an exception if it fails. 475 476 @type uid: string 477 @param uid: The unique id of the device we are renaming 478 @type newId: string 479 @param newId: string of the new id 480 """ 481 facade = self._getFacade() 482 newUid = facade.renameDevice(uid, newId) 483 return DirectResponse.succeed(uid=newUid)
484
485 - def moveDevices(self, uids, target, hashcheck=None, ranges=(), uid=None, 486 params=None, sort='name', dir='ASC', asynchronous=True):
487 """ 488 Moves the devices specified by uids to the organizer specified by 'target'. 489 490 @type uids: [string] 491 @param uids: List of device uids to move 492 @type target: string 493 @param target: Uid of the organizer to move the devices to 494 @type hashcheck: string 495 @param hashcheck: Hashcheck for the devices (from getDevices()) 496 @type ranges: [integer] 497 @param ranges: (optional) List of two integers that are the min/max 498 values of a range of uids to include (default: None) 499 @type uid: string 500 @param uid: (optional) Organizer to use when using ranges to get 501 additional uids (default: None) 502 @type params: dictionary 503 @param params: (optional) Key-value pair of filters for this search. 504 Can be one of the following: name, ipAddress, 505 deviceClass, or productionState (default: None) 506 @type sort: string 507 @param sort: (optional) Key on which to sort the return result (default: 508 'name') 509 @type dir: string 510 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 511 (default: 'ASC') 512 @rtype: DirectResponse 513 @return: B{Properties}: 514 - tree: ([dictionary]) Object representing the new device tree 515 - exports: (integer) Number of devices moved 516 """ 517 if ranges: 518 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 519 uids = filterUidsByPermission(self.context.dmd, ZEN_MANAGE_DEVICE, uids) 520 facade = self._getFacade() 521 522 # In order to display the device name and old location/device class, 523 # we must audit first. This means it's possible we can audit a change 524 # then the command fails, unfortunately. 525 # example: audit('UI.Device.ChangeLocation', uid, location=..., old_location=...) 526 targetType = getDisplayType(facade._getObject(target)) 527 autoRemovalTypes = ('DeviceClass', 'Location') 528 action = ('Change' if targetType in autoRemovalTypes else 'AddTo') + targetType 529 for uid in uids: 530 oldData = {} 531 if targetType == 'Location': # get old location 532 location = facade._getObject(uid).location() 533 locationPath = location.getPrimaryId() if location else '' 534 oldData[targetType] = locationPath 535 elif targetType == 'DeviceClass': 536 deviceClass = facade._getObject(uid).deviceClass() 537 deviceClassPath = deviceClass.getPrimaryId() if deviceClass else '' 538 oldData[targetType] = deviceClassPath 539 audit(['UI.Device', action], uid, 540 data_={targetType:target}, oldData_=oldData) 541 try: 542 targetObj = facade._getObject(target) 543 if Zuul.checkPermission(ZEN_ADMIN_DEVICE, targetObj): 544 result = facade.moveDevices(uids, target, asynchronous=asynchronous) 545 else: 546 return DirectResponse.fail(msg='User does not have permissions to move devices to {0}'.format(target)) 547 except Exception, e: 548 log.exception("Failed to move devices") 549 return DirectResponse.exception(e, 'Failed to move devices.') 550 if asynchronous: 551 return DirectResponse.succeed(new_jobs=Zuul.marshal([result], 552 keys=('uuid', 'description', 'started'))) 553 else: 554 return DirectResponse.succeed(exports=result)
555 556 @require('Manage Device')
557 - def pushChanges(self, uids, hashcheck, ranges=(), uid=None, params=None, 558 sort='name', dir='ASC'):
559 """ 560 Push changes on device(s) configuration to collectors. 561 562 @type uids: [string] 563 @param uids: List of device uids to push changes 564 @type hashcheck: string 565 @param hashcheck: Hashcheck for the devices (from getDevices()) 566 @type ranges: [integer] 567 @param ranges: (optional) List of two integers that are the min/max 568 values of a range of uids to include (default: None) 569 @type uid: string 570 @param uid: (optional) Organizer to use when using ranges to get 571 additional uids (default: None) 572 @type params: dictionary 573 @param params: (optional) Key-value pair of filters for this search. 574 Can be one of the following: name, ipAddress, 575 deviceClass, or productionState (default: None) 576 @type sort: string 577 @param sort: (optional) Key on which to sort the return result (default: 578 'name') 579 @type dir: string 580 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 581 (default: 'ASC') 582 @rtype: DirectResponse 583 @return: Success message 584 """ 585 if ranges: 586 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 587 588 facade = self._getFacade() 589 facade.pushChanges(uids) 590 for uid in uids: 591 audit('UI.Device.PushChanges', uid) 592 return DirectResponse.succeed('Changes pushed to collectors.')
593
594 - def lockDevices(self, uids, hashcheck, ranges=(), updates=False, 595 deletion=False, sendEvent=False, uid=None, params=None, 596 sort='name', dir='ASC'):
597 """ 598 Lock device(s) from changes. 599 600 @type uids: [string] 601 @param uids: List of device uids to lock 602 @type hashcheck: string 603 @param hashcheck: Hashcheck for the devices (from getDevices()) 604 @type ranges: [integer] 605 @param ranges: (optional) List of two integers that are the min/max 606 values of a range of uids to include (default: None) 607 @type updates: boolean 608 @param updates: (optional) True to lock device from updates (default: False) 609 @type deletion: boolean 610 @param deletion: (optional) True to lock device from deletion 611 (default: False) 612 @type sendEvent: boolean 613 @param sendEvent: (optional) True to send an event when an action is 614 blocked by locking (default: False) 615 @type uid: string 616 @param uid: (optional) Organizer to use when using ranges to get 617 additional uids (default: None) 618 @type params: dictionary 619 @param params: (optional) Key-value pair of filters for this search. 620 Can be one of the following: name, ipAddress, 621 deviceClass, or productionState (default: None) 622 @type sort: string 623 @param sort: (optional) Key on which to sort the return result (default: 624 'name') 625 @type dir: string 626 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 627 (default: 'ASC') 628 @rtype: DirectResponse 629 @return: Success or failure message 630 """ 631 if ranges: 632 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 633 facade = self._getFacade() 634 uids = filterUidsByPermission(self.context.dmd, ZEN_MANAGE_DMD, uids) 635 try: 636 facade.setLockState(uids, deletion=deletion, updates=updates, 637 sendEvent=sendEvent) 638 if not deletion and not updates: 639 message = "Unlocked %s devices." % len(uids) 640 else: 641 actions = [] 642 if deletion: 643 actions.append('deletion') 644 if updates: 645 actions.append('updates') 646 message = "Locked %s devices from %s." % (len(uids), 647 ' and '.join(actions)) 648 for uid in uids: 649 audit('UI.Device.EditLocks', uid, 650 deletion=deletion, updates=updates, sendEvent=sendEvent) 651 return DirectResponse.succeed(message) 652 except Exception, e: 653 log.exception(e) 654 return DirectResponse.exception(e, 'Failed to lock devices.')
655 656
657 - def resetIp(self, uids, hashcheck, uid=None, ranges=(), params=None, 658 sort='name', dir='ASC', ip=''):
659 """ 660 Reset IP address(es) of device(s) to the results of a DNS lookup or 661 a manually set address 662 663 @type uids: [string] 664 @param uids: List of device uids with IP's to reset 665 @type hashcheck: string 666 @param hashcheck: Hashcheck for the devices (from getDevices()) 667 @type uid: string 668 @param uid: (optional) Organizer to use when using ranges to get 669 additional uids (default: None) 670 @type ranges: [integer] 671 @param ranges: (optional) List of two integers that are the min/max 672 values of a range of uids to include (default: None) 673 @type params: dictionary 674 @param params: (optional) Key-value pair of filters for this search. 675 Can be one of the following: name, ipAddress, 676 deviceClass, or productionState (default: None) 677 @type sort: string 678 @param sort: (optional) Key on which to sort the return result (default: 679 'name') 680 @type dir: string 681 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 682 (default: 'ASC') 683 @type ip: string 684 @param ip: (optional) IP to set device to. Empty string causes DNS 685 lookup (default: '') 686 @rtype: DirectResponse 687 @return: Success or failure message 688 """ 689 if ranges: 690 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 691 facade = self._getFacade() 692 uids = filterUidsByPermission(self.context.dmd, ZEN_ADMIN_DEVICE, uids) 693 try: 694 for uid in uids: 695 info = facade.getInfo(uid) 696 info.ipAddress = ip # Set to empty causes DNS lookup 697 audit('UI.Device.ResetIP', uid, ip=ip) 698 return DirectResponse('Reset %s IP addresses.' % len(uids)) 699 except Exception, e: 700 log.exception(e) 701 return DirectResponse.exception(e, 'Failed to reset IP addresses.')
702 703 @require('Manage Device')
704 - def resetCommunity(self, uids, hashcheck, uid=None, ranges=(), params=None, 705 sort='name', dir='ASC'):
706 """ 707 Reset SNMP community string(s) on device(s) 708 709 @type uids: [string] 710 @param uids: List of device uids to reset 711 @type hashcheck: string 712 @param hashcheck: Hashcheck for the devices (from getDevices()) 713 @type uid: string 714 @param uid: (optional) Organizer to use when using ranges to get 715 additional uids (default: None) 716 @type ranges: [integer] 717 @param ranges: (optional) List of two integers that are the min/max 718 values of a range of uids to include (default: None) 719 @type params: dictionary 720 @param params: (optional) Key-value pair of filters for this search. 721 Can be one of the following: name, ipAddress, 722 deviceClass, or productionState (default: None) 723 @type sort: string 724 @param sort: (optional) Key on which to sort the return result (default: 725 'name') 726 @type dir: string 727 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 728 (default: 'ASC') 729 @rtype: DirectResponse 730 @return: Success or failure message 731 """ 732 if ranges: 733 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 734 facade = self._getFacade() 735 try: 736 for uid in uids: 737 facade.resetCommunityString(uid) 738 audit('UI.Device.ResetCommunity', uid) 739 return DirectResponse('Reset %s community strings.' % len(uids)) 740 except Exception, e: 741 log.exception(e) 742 return DirectResponse.exception(e, 'Failed to reset community strings.')
743
744 - def setProductionState(self, uids, prodState, hashcheck, uid=None, 745 ranges=(), params=None, sort='name', dir='ASC'):
746 """ 747 Set the production state of device(s). 748 749 @type uids: [string] 750 @param uids: List of device uids to set 751 @type prodState: integer 752 @param prodState: Production state to set device(s) to. 753 @type hashcheck: string 754 @param hashcheck: Hashcheck for the devices (from getDevices()) 755 @type uid: string 756 @param uid: (optional) Organizer to use when using ranges to get 757 additional uids (default: None) 758 @type ranges: [integer] 759 @param ranges: (optional) List of two integers that are the min/max 760 values of a range of uids to include (default: None) 761 @type params: dictionary 762 @param params: (optional) Key-value pair of filters for this search. 763 Can be one of the following: name, ipAddress, 764 deviceClass, or productionState (default: None) 765 @type sort: string 766 @param sort: (optional) Key on which to sort the return result (default: 767 'name') 768 @type dir: string 769 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 770 (default: 'ASC') 771 @rtype: DirectResponse 772 @return: Success or failure message 773 """ 774 if ranges: 775 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 776 facade = self._getFacade() 777 uids = filterUidsByPermission(self.context.dmd, ZEN_CHANGE_DEVICE_PRODSTATE, 778 uids) 779 try: 780 oldStates = {} 781 uids = (uids,) if isinstance(uids, basestring) else uids 782 for uid in uids: 783 device = facade._getObject(uid) 784 if isinstance(device, Device): 785 oldStates[uid] = self.context.convertProdState(device.productionState) 786 787 prodStateName = self.context.convertProdState(prodState) 788 789 auditData = {'productionState': prodStateName} 790 for uid in uids: 791 oldAuditData = {'productionState': oldStates[uid]} 792 audit('UI.Device.Edit', uid, oldData_=oldAuditData, data_=auditData) 793 facade.setProductionState(uids, prodState, asynchronous=True) 794 return DirectResponse('Set %s devices to %s.' % ( 795 len(uids), prodStateName)) 796 except Exception, e: 797 log.exception(e) 798 return DirectResponse.exception(e, 'Failed to change production state.')
799
800 - def setPriority(self, uids, priority, hashcheck, uid=None, ranges=(), 801 params=None, sort='name', dir='ASC'):
802 """ 803 Set device(s) priority. 804 805 @type uids: [string] 806 @param uids: List of device uids to set 807 @type priority: integer 808 @param priority: Priority to set device(s) to. 809 @type hashcheck: string 810 @param hashcheck: Hashcheck for the devices (from getDevices()) 811 @type uid: string 812 @param uid: (optional) Organizer to use when using ranges to get 813 additional uids (default: None) 814 @type ranges: [integer] 815 @param ranges: (optional) List of two integers that are the min/max 816 values of a range of uids to include (default: None) 817 @type params: dictionary 818 @param params: (optional) Key-value pair of filters for this search. 819 Can be one of the following: name, ipAddress, 820 deviceClass, or productionState (default: None) 821 @type sort: string 822 @param sort: (optional) Key on which to sort the return result (default: 823 'name') 824 @type dir: string 825 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 826 (default: 'ASC') 827 @rtype: DirectResponse 828 @return: Success or failure message 829 """ 830 if ranges: 831 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 832 facade = self._getFacade() 833 uids = filterUidsByPermission(self.context.dmd, ZEN_MANAGE_DEVICE, uids) 834 try: 835 for uid in uids: 836 info = facade.getInfo(uid) 837 oldPriorityLabel = info.priorityLabel 838 info.priority = priority 839 notify(IndexingEvent(info._object)) 840 audit('UI.Device.Edit', uid, 841 priority=info.priorityLabel, 842 oldData_={'priority':oldPriorityLabel}) 843 return DirectResponse('Set %s devices to %s priority.' % ( 844 len(uids), info.priorityLabel)) 845 except Exception, e: 846 log.exception(e) 847 return DirectResponse.exception(e, 'Failed to change priority.')
848
849 - def moveCollectorDevices(self, srcCollectors, dstCollector, hashcheck, uid=None, ranges=(), 850 params=None, sort='name', dir='ASC', moveData=False, 851 asynchronous=True):
852 """ 853 Move all devices under one or more collectors to another collector 854 855 The signature is exactly the same as setCollector(), except that the 856 'uids' parameter is replaced with 'srcCollectors' 857 858 @type srcCollectors: list of strings 859 @param srcCollectors: The collectors to move all devices from 860 """ 861 monitorFacade = Zuul.getFacade('monitors', self.context) 862 if isinstance(srcCollectors, basestring): 863 srcCollectorObjs = monitorFacade.get(srcCollectors) 864 else: 865 srcCollectorObjs = [] 866 for collector in srcCollectors: 867 srcCollectorObjs.append(monitorFacade.get(collector)) 868 deviceUids = [] 869 for collector in srcCollectorObjs: 870 deviceUids.extend([ dev.getPrimaryId() for dev in collector.getDevices() ]) 871 return self.setCollector(deviceUids, dstCollector, hashcheck, uid, ranges, 872 params, sort, dir, moveData, asynchronous)
873
874 - def setCollector(self, uids, collector, hashcheck, uid=None, ranges=(), 875 params=None, sort='name', dir='ASC', moveData=False, 876 asynchronous=True):
877 """ 878 Set device(s) collector. 879 880 @type uids: [string] 881 @param uids: List of device uids to set 882 @type collector: string 883 @param collector: Collector to set devices to 884 @type hashcheck: string 885 @param hashcheck: Hashcheck for the devices (from getDevices()) 886 @type uid: string 887 @param uid: (optional) Organizer to use when using ranges to get 888 additional uids (default: None) 889 @type ranges: [integer] 890 @param ranges: (optional) List of two integers that are the min/max 891 values of a range of uids to include (default: None) 892 @type params: dictionary 893 @param params: (optional) Key-value pair of filters for this search. 894 Can be one of the following: name, ipAddress, 895 deviceClass, or productionState (default: None) 896 @type sort: string 897 @param sort: (optional) Key on which to sort the return result (default: 898 'name') 899 @type dir: string 900 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 901 (default: 'ASC') 902 @rtype: DirectResponse 903 @return: Success or failure message 904 """ 905 if ranges: 906 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 907 facade = self._getFacade() 908 uids = filterUidsByPermission(self.context.dmd, ZEN_ADMIN_DEVICE, uids) 909 try: 910 # iterate through uids so that logging works as expected 911 result = facade.setCollector(uids, collector, asynchronous) 912 for devUid in uids: 913 audit('UI.Device.ChangeCollector', devUid, collector=collector) 914 if asynchronous and result: 915 return DirectResponse.succeed(new_jobs=Zuul.marshal(result, 916 keys=('uuid', 'description', 'started'))) 917 else: 918 return DirectResponse.succeed('Changed collector to %s for %s devices.' % 919 (collector, len(uids))) 920 except Exception, e: 921 log.exception(e) 922 return DirectResponse.exception(e, 'Failed to change the collector.')
923
924 - def setComponentsMonitored(self, uids, hashcheck, monitor=False, uid=None, 925 ranges=(), meta_type=None, keys=None, 926 start=0, limit=50, sort='name', dir='ASC', 927 name=None):
928 """ 929 Set the monitoring flag for component(s) 930 931 @type uids: [string] 932 @param uids: List of component uids to set 933 @type hashcheck: string 934 @param hashcheck: Hashcheck for the components (from getComponents()) 935 @type monitor: boolean 936 @param monitor: (optional) True to monitor component (default: False) 937 @type uid: string 938 @param uid: (optional) Device to use when using ranges to get 939 additional uids (default: None) 940 @type ranges: [integer] 941 @param ranges: (optional) List of two integers that are the min/max 942 values of a range of uids to include (default: None) 943 @type meta_type: string 944 @param meta_type: (optional) The meta type of the components to retrieve 945 (default: None) 946 @type keys: [string] 947 @param keys: not used 948 @type start: integer 949 @param start: (optional) Offset to return the results from; used in 950 pagination (default: 0) 951 @type limit: integer 952 @param limit: (optional) Number of items to return; used in pagination 953 (default: 50) 954 @type sort: string 955 @param sort: (optional) Key on which to sort the return result (default: 956 'name') 957 @type dir: string 958 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 959 (default: 'ASC') 960 @type name: string 961 @param name: (optional) Component name to search for when loading ranges 962 (default: None) 963 @rtype: DirectResponse 964 @return: Success or failure message 965 """ 966 if ranges: 967 uids += self.loadComponentRanges(ranges, hashcheck, uid, (), 968 meta_type, start, limit, sort, 969 dir, name) 970 facade = self._getFacade() 971 facade.setMonitor(uids, monitor) 972 action = 'SetMonitored' if monitor else 'SetUnmonitored' 973 for uid in uids: 974 audit(['UI.Component', action], uid) 975 return DirectResponse.succeed(('Set monitoring to %s for %s' 976 ' components.') % (monitor, len(uids)))
977
978 - def lockComponents(self, uids, hashcheck, uid=None, ranges=(), 979 updates=False, deletion=False, sendEvent=False, 980 meta_type=None, keys=None, start=0, limit=50, 981 sort='name', dir='ASC', name=None):
982 """ 983 Lock component(s) from changes. 984 985 @type uids: [string] 986 @param uids: List of component uids to lock 987 @type hashcheck: string 988 @param hashcheck: Hashcheck for the components (from getComponents()) 989 @type uid: string 990 @param uid: (optional) Device to use when using ranges to get 991 additional uids (default: None) 992 @type ranges: [integer] 993 @param ranges: (optional) List of two integers that are the min/max 994 values of a range of uids to include (default: None) 995 @type updates: boolean 996 @param updates: (optional) True to lock component from updates (default: False) 997 @type deletion: boolean 998 @param deletion: (optional) True to lock component from deletion 999 (default: False) 1000 @type sendEvent: boolean 1001 @param sendEvent: (optional) True to send an event when an action is 1002 blocked by locking (default: False) 1003 @type meta_type: string 1004 @param meta_type: (optional) The meta type of the components to retrieve 1005 (default: None) 1006 @type keys: [string] 1007 @param keys: not used 1008 @type start: integer 1009 @param start: (optional) Offset to return the results from; used in 1010 pagination (default: 0) 1011 @type limit: integer 1012 @param limit: (optional) Number of items to return; used in pagination 1013 (default: 50) 1014 @type sort: string 1015 @param sort: (optional) Key on which to sort the return result (default: 1016 'name') 1017 @type dir: string 1018 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 1019 (default: 'ASC') 1020 @type name: string 1021 @param name: (optional) Component name to search for when loading ranges 1022 (default: None) 1023 @rtype: DirectResponse 1024 @return: Success or failure message 1025 """ 1026 if ranges: 1027 uids += self.loadComponentRanges(ranges, hashcheck, uid, (), 1028 meta_type, start, limit, sort, 1029 dir, name) 1030 facade = self._getFacade() 1031 try: 1032 facade.setLockState(uids, deletion=deletion, updates=updates, 1033 sendEvent=sendEvent) 1034 if not deletion and not updates: 1035 message = "Unlocked %d components." % len(uids) 1036 else: 1037 actions = [] 1038 if deletion: 1039 actions.append('deletion') 1040 if updates: 1041 actions.append('updates') 1042 actions = ' and '.join(actions) 1043 message = "Locked %d components from %s." % (len(uids), actions) 1044 for uid in uids: 1045 audit('UI.Component.EditLocks', uid, 1046 deletion=deletion, updates=updates, sendEvents=sendEvent) 1047 return DirectResponse.succeed(message) 1048 except Exception, e: 1049 log.exception(e) 1050 return DirectResponse.exception(e, 'Failed to lock components.')
1051
1052 - def deleteComponents(self, uids, hashcheck, uid=None, ranges=(), 1053 meta_type=None, keys=None, start=0, limit=50, 1054 sort='name', dir='ASC', name=None):
1055 """ 1056 Delete device component(s). 1057 1058 @type uids: [string] 1059 @param uids: List of component uids to delete 1060 @type hashcheck: string 1061 @param hashcheck: Hashcheck for the components (from getComponents()) 1062 @type uid: string 1063 @param uid: (optional) Device to use when using ranges to get 1064 additional uids (default: None) 1065 @type ranges: [integer] 1066 @param ranges: (optional) List of two integers that are the min/max 1067 values of a range of uids to include (default: None) 1068 @type meta_type: string 1069 @param meta_type: (optional) The meta type of the components to retrieve 1070 (default: None) 1071 @type keys: [string] 1072 @param keys: not used 1073 @type start: integer 1074 @param start: (optional) Offset to return the results from; used in 1075 pagination (default: 0) 1076 @type limit: integer 1077 @param limit: (optional) Number of items to return; used in pagination 1078 (default: 50) 1079 @type sort: string 1080 @param sort: (optional) Key on which to sort the return result (default: 1081 'name') 1082 @type dir: string 1083 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 1084 (default: 'ASC') 1085 @type name: string 1086 @param name: (optional) Component name to search for when loading ranges 1087 (default: None) 1088 @rtype: DirectResponse 1089 @return: Success or failure message 1090 """ 1091 if ranges: 1092 uids += self.loadComponentRanges(ranges, hashcheck, uid, (), 1093 meta_type, start, limit, sort, 1094 dir, name) 1095 facade = self._getFacade() 1096 try: 1097 facade.deleteComponents(uids) 1098 for uid in uids: 1099 audit('UI.Component.Delete', uid) 1100 return DirectResponse.succeed('Components deleted.') 1101 except Exception, e: 1102 log.exception(e) 1103 return DirectResponse.exception(e, 'Failed to delete components.')
1104
1105 - def removeDevices(self, uids, hashcheck, action="remove", uid=None, 1106 ranges=(), params=None, sort='name', dir='ASC', 1107 deleteEvents=False, deletePerf=False 1108 ):
1109 """ 1110 Remove/delete device(s). 1111 1112 @type uids: [string] 1113 @param uids: List of device uids to remove 1114 @type hashcheck: string 1115 @param hashcheck: Hashcheck for the devices (from getDevices()) 1116 @type action: string 1117 @param action: Action to take. 'remove' to remove devices from organizer 1118 uid, and 'delete' to delete the device from Zenoss. 1119 @type uid: string 1120 @param uid: (optional) Organizer to use when using ranges to get 1121 additional uids and/or to remove device (default: None) 1122 @type ranges: [integer] 1123 @param ranges: (optional) List of two integers that are the min/max 1124 values of a range of uids to include (default: None) 1125 @type params: dictionary 1126 @param params: (optional) Key-value pair of filters for this search. 1127 Can be one of the following: name, ipAddress, 1128 deviceClass, or productionState (default: None) 1129 @type sort: string 1130 @param sort: (optional) Key on which to sort the return result (default: 1131 'name') 1132 @type dir: string 1133 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 1134 (default: 'ASC') 1135 @type deleteEvents: bool 1136 @param deleteEvents: will remove all the events for the devices as well 1137 @type deletePerf: bool 1138 @param deletePerf: will remove all the perf data for the devices 1139 @rtype: DirectResponse 1140 @return: B{Properties}: 1141 - devtree: ([dictionary]) Object representing the new device tree 1142 - grptree: ([dictionary]) Object representing the new group tree 1143 - systree: ([dictionary]) Object representing the new system tree 1144 - loctree: ([dictionary]) Object representing the new location tree 1145 """ 1146 if ranges: 1147 uids += self.loadRanges(ranges, hashcheck, uid, params, sort, dir) 1148 facade = self._getFacade() 1149 removedUids = tuple() 1150 uids = filterUidsByPermission(self.context.dmd, ZEN_DELETE_DEVICE, uids) 1151 try: 1152 if action == "remove": 1153 removed = facade.removeDevices(uids, organizer=uid) 1154 1155 # uid could be an object or string. 1156 organizer = facade._getObject(uid) if isinstance(uid, basestring) else uid 1157 organizerType = organizer.meta_type 1158 action = 'RemoveFrom' + organizerType # Ex: RemoveFromLocation 1159 removedUids = map(lambda x: x.uid, removed) 1160 for devuid in removedUids: 1161 # Ex: ('UI.Device.RemoveFromLocation', deviceUid, location=...) 1162 audit('UI.Device.%s' % action, devuid, data_={organizerType:uid}) 1163 notRemovedUids = list(set(uids) - set(removedUids)) 1164 return DirectResponse.succeed( 1165 removedUids=removedUids, 1166 notRemovedUids=notRemovedUids) 1167 elif action == "delete": 1168 for devuid in uids: 1169 audit('UI.Device.Delete', devuid, 1170 deleteEvents=deleteEvents, 1171 deletePerf=deletePerf) 1172 facade.deleteDevices(uids, 1173 deleteEvents=deleteEvents, 1174 deletePerf=deletePerf) 1175 return DirectResponse.succeed() 1176 except Exception, e: 1177 log.exception(e) 1178 return DirectResponse.exception(e, 'Failed to remove devices.')
1179 1180 @serviceConnectionError
1181 - def getGraphDefs(self, uid, drange=None):
1182 """ 1183 Returns the url and title for each graph 1184 for the object passed in. 1185 @type uid: string 1186 @param uid: unique identifier of an object 1187 """ 1188 facade = self._getFacade() 1189 data = facade.getGraphDefs(uid, drange) 1190 return DirectResponse(data=Zuul.marshal(data))
1191
1192 - def loadRanges(self, ranges, hashcheck, uid=None, params=None, 1193 sort='name', dir='ASC'):
1194 """ 1195 Get a range of device uids. 1196 1197 @type ranges: [integer] 1198 @param ranges: List of two integers that are the min/max values of a 1199 range of uids 1200 @type hashcheck: string 1201 @param hashcheck: Hashcheck for the devices (from getDevices()) 1202 @type uid: string 1203 @param uid: (optional) Organizer to use to get uids (default: None) 1204 @type params: dictionary 1205 @param params: (optional) Key-value pair of filters for this search. 1206 Can be one of the following: name, ipAddress, 1207 deviceClass, or productionState (default: None) 1208 @type sort: string 1209 @param sort: (optional) Key on which to sort the return result (default: 1210 'name') 1211 @type dir: string 1212 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 1213 (default: 'ASC') 1214 @rtype: [string] 1215 @return: A list of device uids 1216 """ 1217 facade = self._getFacade() 1218 if isinstance(params, basestring): 1219 params = unjson(params) 1220 devs = facade.getDeviceBrains(uid, limit=None, sort=sort, dir=dir, 1221 params=params, hashcheck=hashcheck) 1222 uids = [] 1223 for start, stop in sorted(ranges): 1224 uids.extend(b.getPath() for b in islice(devs, start, stop + 1)) 1225 return uids
1226
1227 - def loadComponentRanges(self, ranges, hashcheck, uid=None, types=(), 1228 meta_type=(), start=0, limit=None, sort='name', 1229 dir='ASC', name=None):
1230 """ 1231 Get a range of component uids. 1232 1233 @type ranges: [integer] 1234 @param ranges: List of two integers that are the min/max values of a 1235 range of uids 1236 @type hashcheck: string 1237 @param hashcheck: not used 1238 @type uid: string 1239 @param uid: (optional) Device to use to get uids (default: None) 1240 @type types: [string] 1241 @param types: (optional) The types of components to retrieve (default: None) 1242 @type meta_type: string 1243 @param meta_type: (optional) The meta type of the components to retrieve 1244 (default: None) 1245 @type start: integer 1246 @param start: (optional) Offset to return the results from; used in 1247 pagination (default: 0) 1248 @type limit: integer 1249 @param limit: (optional) Number of items to return; used in pagination 1250 (default: None) 1251 @type sort: string 1252 @param sort: (optional) Key on which to sort the return result (default: 1253 'name') 1254 @type dir: string 1255 @param dir: (optional) Sort order; can be either 'ASC' or 'DESC' 1256 (default: 'ASC') 1257 @type name: string 1258 @param name: (optional) Component name to search for when loading ranges 1259 (default: None) 1260 @rtype: [string] 1261 @return: A list of component uids 1262 """ 1263 if uid is None: 1264 uid = "/".join(self.context.getPhysicalPath()) 1265 facade = self._getFacade() 1266 comps = facade.getComponents(uid, types, meta_type, start, limit, sort, 1267 dir, name) 1268 uids = [] 1269 for start, stop in sorted(ranges): 1270 uids.extend(b.uid for b in islice(comps, start, stop)) 1271 return uids
1272 1273 @serviceConnectionError
1274 - def getUserCommands(self, uid):
1275 """ 1276 Get a list of user commands for a device uid. 1277 1278 @type uid: string 1279 @param uid: Device to use to get user commands 1280 @rtype: [dictionary] 1281 @return: List of objects representing user commands 1282 """ 1283 facade = self._getFacade() 1284 cmds = facade.getUserCommands(uid) 1285 return Zuul.marshal(cmds, ['id', 'description'])
1286
1287 - def getProductionStates(self, **kwargs):
1288 """ 1289 Get a list of available production states. 1290 1291 @rtype: [dictionary] 1292 @return: List of name/value pairs of available production states 1293 """ 1294 return DirectResponse(data=[dict(name=s.split(':')[0], 1295 value=int(s.split(':')[1])) for s in 1296 self.context.dmd.prodStateConversions])
1297
1298 - def getPriorities(self, **kwargs):
1299 """ 1300 Get a list of available device priorities. 1301 1302 @rtype: [dictionary] 1303 @return: List of name/value pairs of available device priorities 1304 """ 1305 return DirectResponse(data=[dict(name=s.split(':')[0], 1306 value=int(s.split(':')[1])) for s in 1307 self.context.dmd.priorityConversions])
1308
1309 - def getCollectors(self):
1310 """ 1311 Get a list of available collectors. 1312 1313 @rtype: [string] 1314 @return: List of collectors 1315 """ 1316 return self.context.dmd.Monitors.getPerformanceMonitorNames()
1317
1318 - def getDeviceClasses(self, **data):
1319 """ 1320 Get a list of all device classes. 1321 1322 @rtype: DirectResponse 1323 @return: B{Properties}: 1324 - deviceClasses: ([dictionary]) List of device classes 1325 - totalCount: (integer) Total number of device classes 1326 """ 1327 devices = self.context.dmd.Devices 1328 deviceClasses = devices.getOrganizerNames(addblank=True) 1329 result = [{'name': name} for name in deviceClasses] 1330 return DirectResponse(deviceClasses=result, totalCount=len(result))
1331
1332 - def getSystems(self, **data):
1333 """ 1334 Get a list of all systems. 1335 1336 @rtype: DirectResponse 1337 @return: B{Properties}: 1338 - systems: ([dictionary]) List of systems 1339 - totalCount: (integer) Total number of systems 1340 """ 1341 systems = self.context.dmd.Systems.getOrganizerNames() 1342 result = [{'name': name} for name in systems if name != '/'] 1343 return DirectResponse(systems=result, totalCount=len(result))
1344
1345 - def getGroups(self, **data):
1346 """ 1347 Get a list of all groups. 1348 1349 @rtype: DirectResponse 1350 @return: B{Properties}: 1351 - systems: ([dictionary]) List of groups 1352 - totalCount: (integer) Total number of groups 1353 """ 1354 groups = self.context.dmd.Groups.getOrganizerNames() 1355 result = [{'name': name} for name in groups if name != '/'] 1356 return DirectResponse(groups=result, totalCount=len(result))
1357
1358 - def getLocations(self, **data):
1359 """ 1360 Get a list of all locations. 1361 1362 @rtype: DirectResponse 1363 @return: B{Properties}: 1364 - systems: ([dictionary]) List of locations 1365 - totalCount: (integer) Total number of locations 1366 """ 1367 locations = self.context.dmd.Locations.getOrganizerNames() 1368 result = [{'name': name} for name in locations if name != '/'] 1369 return DirectResponse(locations=result, totalCount=len(result))
1370
1371 - def getManufacturerNames(self, **data):
1372 """ 1373 Get a list of all manufacturer names. 1374 1375 @rtype: DirectResponse 1376 @return: B{Properties}: 1377 - manufacturers: ([dictionary]) List of manufacturer names 1378 - totalCount: (integer) Total number of manufacturer names 1379 """ 1380 names = self.context.dmd.Manufacturers.getManufacturerNames() 1381 result = [{'name': name} for name in names] 1382 return DirectResponse(manufacturers=result, totalCount=len(result))
1383
1384 - def getHardwareProductNames(self, manufacturer='', **data):
1385 """ 1386 Get a list of all hardware product names from a manufacturer. 1387 1388 @type manufacturer: string 1389 @param manufacturer: Manufacturer name 1390 @rtype: DirectResponse 1391 @return: B{Properties}: 1392 - productNames: ([dictionary]) List of hardware product names 1393 - totalCount: (integer) Total number of hardware product names 1394 """ 1395 manufacturers = self.context.dmd.Manufacturers 1396 names = manufacturers.getProductNames(manufacturer, 'HardwareClass') 1397 result = [{'name': name} for name in names] 1398 return DirectResponse(productNames=result, totalCount=len(result))
1399
1400 - def getOSProductNames(self, manufacturer='', **data):
1401 """ 1402 Get a list of all OS product names from a manufacturer. 1403 1404 @type manufacturer: string 1405 @param manufacturer: Manufacturer name 1406 @rtype: DirectResponse 1407 @return: B{Properties}: 1408 - productNames: ([dictionary]) List of OS product names 1409 - totalCount: (integer) Total number of OS product names 1410 """ 1411 manufacturers = self.context.dmd.Manufacturers 1412 names = manufacturers.getProductNames(manufacturer, 'OS') 1413 result = [{'name': name} for name in names] 1414 return DirectResponse(productNames=result, totalCount=len(result))
1415
1416 - def addDevice(self, deviceName, deviceClass, title=None, 1417 snmpCommunity="", snmpPort=161, manageIp="", 1418 model=False, collector='localhost', rackSlot=0, 1419 locationPath="", systemPaths=[], groupPaths=[], 1420 productionState=1000, comments="", hwManufacturer="", 1421 hwProductName="", osManufacturer="", osProductName="", 1422 priority=3, tag="", serialNumber="", zCommandUsername="", 1423 zCommandPassword="", zWinUser="", zWinPassword="", 1424 zProperties={}, cProperties={},):
1425 1426 """ 1427 Add a device. 1428 1429 @type deviceName: string 1430 @param deviceName: Name or IP of the new device 1431 @type deviceClass: string 1432 @param deviceClass: The device class to add new device to 1433 @type title: string 1434 @param title: (optional) The title of the new device (default: '') 1435 @type snmpCommunity: string 1436 @param snmpCommunity: (optional) A specific community string to use for 1437 this device. (default: '') 1438 @type snmpPort: integer 1439 @param snmpPort: (optional) SNMP port on new device (default: 161) 1440 @type manageIp: string 1441 @param manageIp: (optional) Management IP address on new device (default: 1442 empty/derive from DNS) 1443 @type locationPath: string 1444 @param locationPath: (optional) Organizer path of the location for this device 1445 @type systemPaths: List (strings) 1446 @param systemPaths: (optional) List of organizer paths for the device 1447 @type groupPaths: List (strings) 1448 @param groupPaths: (optional) List of organizer paths for the device 1449 @type model: boolean 1450 @param model: (optional) True to model device at add time (default: False) 1451 @type collector: string 1452 @param collector: (optional) Collector to use for new device (default: 1453 localhost) 1454 @type rackSlot: string 1455 @param rackSlot: (optional) Rack slot description (default: '') 1456 @type productionState: integer 1457 @param productionState: (optional) Production state of the new device 1458 (default: 1000) 1459 @type comments: string 1460 @param comments: (optional) Comments on this device (default: '') 1461 @type hwManufacturer: string 1462 @param hwManufacturer: (optional) Hardware manufacturer name (default: '') 1463 @type hwProductName: string 1464 @param hwProductName: (optional) Hardware product name (default: '') 1465 @type osManufacturer: string 1466 @param osManufacturer: (optional) OS manufacturer name (default: '') 1467 @type osProductName: string 1468 @param osProductName: (optional) OS product name (default: '') 1469 @type priority: integer 1470 @param priority: (optional) Priority of this device (default: 3) 1471 @type tag: string 1472 @param tag: (optional) Tag number of this device (default: '') 1473 @type serialNumber: string 1474 @param serialNumber: (optional) Serial number of this device (default: '') 1475 @type zCommandUsername: string 1476 @param zWinUser: (optional) Username for WMI (default: '') 1477 @type zCommandPassword: string 1478 @param zWinPassword: (optional) Password for WMI (default: '') 1479 @rtype: DirectResponse 1480 @return: B{Properties}: 1481 - jobId: (string) ID of the add device job 1482 """ 1483 # check for permission in the device organizer to which we are 1484 # adding the device 1485 facade = self._getFacade() 1486 organizerUid = '/zport/dmd/Devices' + deviceClass 1487 organizer = facade._getObject(organizerUid) 1488 if not Zuul.checkPermission("Manage Device", organizer): 1489 raise Unauthorized('Calling AddDevice requires ' + 1490 'Manage Device permission on %s' % deviceClass) 1491 1492 if title is None: 1493 title = deviceName 1494 1495 # the device name is used as part of the URL, so any unicode characters 1496 # will be stripped before saving. Pre-empt this and make the device name 1497 # safe prior to the uniqueness check. 1498 safeDeviceName = organizer.prepId(deviceName) 1499 1500 device = facade.getDeviceByIpAddress(safeDeviceName, collector, manageIp) 1501 if device: 1502 return DirectResponse.fail(deviceUid=device.getPrimaryId(), 1503 msg="Device %s already exists. <a href='%s'>Go to the device</a>" % (deviceName, device.getPrimaryId())) 1504 1505 if isinstance(systemPaths, basestring): 1506 systemPaths = [systemPaths] 1507 if isinstance(groupPaths, basestring): 1508 groupPaths = [groupPaths] 1509 1510 jobrecords = self._getFacade().addDevice(deviceName, 1511 deviceClass, 1512 title, 1513 snmpCommunity, 1514 snmpPort, 1515 manageIp, 1516 model, 1517 collector, 1518 rackSlot, 1519 productionState, 1520 comments, 1521 hwManufacturer, 1522 hwProductName, 1523 osManufacturer, 1524 osProductName, 1525 priority, 1526 tag, 1527 serialNumber, 1528 locationPath, 1529 zCommandUsername, 1530 zCommandPassword, 1531 zWinUser, 1532 zWinPassword, 1533 systemPaths, 1534 groupPaths, 1535 zProperties, 1536 cProperties, 1537 ) 1538 1539 deviceUid = '/'.join([organizerUid, 'devices', deviceName]) 1540 # Zero groups or systems sends as [''] so exclude that case. 1541 hasGroups = len(groupPaths) > 1 or (groupPaths and groupPaths[0]) 1542 hasSystems = len(systemPaths) > 1 or (systemPaths and systemPaths[0]) 1543 auditData = { 1544 'deviceClass': '/Devices' + deviceClass, 1545 'location': '/Locations' + locationPath if locationPath else None, 1546 'deviceGroups': ['/Groups' + x for x in groupPaths] if hasGroups else None, 1547 'systems': ['/Systems' + x for x in systemPaths] if hasSystems else None, 1548 'device_name': title if title else deviceName, # see Trac #30109 1549 'collector': collector, 1550 'model': str(model), # show value even if False 1551 'productionState': self.context.convertProdState(productionState), 1552 'priority': self.context.convertPriority(priority), 1553 } 1554 audit('UI.Device.Add', deviceUid, data_=auditData) 1555 return DirectResponse.succeed(new_jobs=Zuul.marshal(jobrecords, keys=('uuid', 'description')))
1556 1557 @require('Manage Device')
1558 - def remodel(self, deviceUid):
1559 """ 1560 Submit a job to have a device remodeled. 1561 1562 @type deviceUid: string 1563 @param deviceUid: Device uid to have local template 1564 @rtype: DirectResponse 1565 @return: B{Properties}: 1566 - jobId: (string) ID of the add device job 1567 """ 1568 jobStatus = self._getFacade().remodel(deviceUid) 1569 audit('UI.Device.Remodel', deviceUid) 1570 return DirectResponse.succeed(jobId=jobStatus.id)
1571 1572 @require('Edit Local Templates')
1573 - def addLocalTemplate(self, deviceUid, templateId):
1574 """ 1575 Adds a local template on a device. 1576 1577 @type deviceUid: string 1578 @param deviceUid: Device uid to have local template 1579 @type templateId: string 1580 @param templateId: Name of the new template 1581 @rtype: DirectResponse 1582 @return: Success message 1583 """ 1584 facade = self._getFacade() 1585 facade.addLocalTemplate(deviceUid, templateId) 1586 audit('UI.Device.AddLocalTemplate', deviceUid, template=templateId) 1587 return DirectResponse.succeed()
1588 1589 @require('Edit Local Templates')
1590 - def removeLocalTemplate(self, deviceUid, templateUid):
1591 """ 1592 Removes a locally defined template on a device. 1593 1594 @type deviceUid: string 1595 @param deviceUid: Device uid that has local template 1596 @type templateUid: string 1597 @param templateUid: Name of the template to remove 1598 @rtype: DirectResponse 1599 @return: Success message 1600 """ 1601 facade = self._getFacade() 1602 facade.removeLocalTemplate(deviceUid, templateUid) 1603 audit('UI.Device.RemoveLocalTemplate', deviceUid, template=templateUid) 1604 return DirectResponse.succeed()
1605
1606 - def getLocalTemplates(self, query, uid):
1607 """ 1608 Get a list of locally defined templates on a device. 1609 1610 @type query: string 1611 @param query: not used 1612 @type uid: string 1613 @param uid: Device uid to query for templates 1614 @rtype: DirectResponse 1615 @return: B{Properties}: 1616 - data: ([dictionary]) List of objects representing local templates 1617 """ 1618 facade = self._getFacade() 1619 templates = facade.getLocalTemplates(uid) 1620 data = [] 1621 for template in templates: 1622 data.append(dict(label=template['text'], uid=template['uid'])) 1623 return DirectResponse.succeed(data=data)
1624 1625 @serviceConnectionError
1626 - def getTemplates(self, id):
1627 """ 1628 Get a list of available templates for a device. 1629 1630 @type id: string 1631 @param id: Device uid to query for templates 1632 @rtype: DirectResponse 1633 @return: B{Properties}: 1634 - data: ([dictionary]) List of objects representing templates 1635 """ 1636 facade = self._getFacade() 1637 templates = facade.getTemplates(id) 1638 return Zuul.marshal(templates)
1639 1640 @serviceConnectionError
1641 - def getUnboundTemplates(self, uid):
1642 """ 1643 Get a list of unbound templates for a device. 1644 1645 @type uid: string 1646 @param uid: Device uid to query for templates 1647 @rtype: DirectResponse 1648 @return: B{Properties}: 1649 - data: ([dictionary]) List of objects representing templates 1650 """ 1651 facade = self._getFacade() 1652 templates = facade.getUnboundTemplates(uid) 1653 data = [] 1654 for template in templates: 1655 label = '%s (%s)' % (template.titleOrId(), template.getUIPath()) 1656 data.append([template.id, label]) 1657 return DirectResponse.succeed(data=Zuul.marshal(data))
1658 1659 @serviceConnectionError
1660 - def getBoundTemplates(self, uid):
1661 """ 1662 Get a list of bound templates for a device. 1663 1664 @type uid: string 1665 @param uid: Device uid to query for templates 1666 @rtype: DirectResponse 1667 @return: B{Properties}: 1668 - data: ([dictionary]) List of objects representing templates 1669 """ 1670 facade = self._getFacade() 1671 templates = facade.getBoundTemplates(uid) 1672 data = [] 1673 for template in templates: 1674 label = '%s (%s)' % (template.titleOrId(), template.getUIPath()) 1675 data.append([template.id, label]) 1676 return DirectResponse.succeed(data=Zuul.marshal(data))
1677 1678 @require('Edit Local Templates')
1679 - def setBoundTemplates(self, uid, templateIds):
1680 """ 1681 Set a list of templates as bound to a device. 1682 1683 @type uid: string 1684 @param uid: Device uid to bind templates to 1685 @type templateIds: [string] 1686 @param templateIds: List of template uids to bind to device 1687 @rtype: DirectResponse 1688 @return: Success message 1689 """ 1690 facade = self._getFacade() 1691 try: 1692 facade.setBoundTemplates(uid, templateIds) 1693 except DatapointNameConfict, e: 1694 log.info("Failed to bind templates for {}: {}".format(uid, e)) 1695 return DirectResponse.exception(e, 'Failed to bind templates.') 1696 audit('UI.Device.BindTemplates', uid, templates=templateIds) 1697 return DirectResponse.succeed()
1698 1699 @require('Edit Local Templates')
1700 - def resetBoundTemplates(self, uid):
1701 """ 1702 Remove all bound templates from a device. 1703 1704 @type uid: string 1705 @param uid: Device uid to remove bound templates from 1706 @rtype: DirectResponse 1707 @return: Success message 1708 """ 1709 facade = self._getFacade() 1710 facade.resetBoundTemplates(uid) 1711 audit('UI.Device.ResetBoundTemplates', uid) 1712 return DirectResponse.succeed()
1713 1714 @require('Edit Local Templates')
1715 - def bindOrUnbindTemplate(self, uid, templateUid):
1716 """ 1717 Bind an unbound template or unbind a bound template from a device. 1718 1719 @type uid: string 1720 @param uid: Device uid to bind/unbind template 1721 @type templateUid: string 1722 @param templateUid: Template uid to bind/unbind 1723 @rtype: DirectResponse 1724 @return: Success message 1725 """ 1726 facade = self._getFacade() 1727 template = facade._getObject(templateUid) 1728 templateIds = [t.id for t in facade.getBoundTemplates(uid)] 1729 # not bound 1730 if not template.id in templateIds: 1731 self.setBoundTemplates(uid, templateIds + [template.id]) 1732 audit('UI.Device.BindTemplate', uid, template=templateUid) 1733 else: 1734 # already bound so unbind it 1735 templateIds = [t for t in templateIds if t != template.id] 1736 self.setBoundTemplates(uid, templateIds) 1737 audit('UI.Device.UnbindTemplate', uid, template=templateUid) 1738 return DirectResponse.succeed()
1739
1740 - def getOverridableTemplates(self, query, uid):
1741 """ 1742 Get a list of available templates on a device that can be overridden. 1743 1744 @type query: string 1745 @param query: not used 1746 @type uid: string 1747 @param uid: Device to query for overridable templates 1748 @rtype: DirectResponse 1749 @return: B{Properties}: 1750 - data: ([dictionary]) List of objects representing templates 1751 """ 1752 facade = self._getFacade() 1753 templates = facade.getOverridableTemplates(uid) 1754 # we just need the text and the id (for our combobox) 1755 data = [] 1756 for template in templates: 1757 label = '%s (%s)' % (template.text, template.getUIPath()) 1758 data.append(dict(label=label, uid=template.uid)) 1759 return DirectResponse.succeed(data=data)
1760 1761 @require('Manage DMD')
1762 - def clearGeocodeCache(self):
1763 """ 1764 Clear the Google Maps geocode cache. 1765 1766 @rtype: DirectResponse 1767 @return: Success message 1768 """ 1769 facade = self._getFacade() 1770 facade.clearGeocodeCache() 1771 audit('UI.GeocodeCache.Clear') 1772 return DirectResponse.succeed()
1773
1774 - def getConnectionInfo(self, uid):
1775 """ 1776 Returns the zproperty information about those zproperties which comprise 1777 the credentials 1778 @rtype: List of Dictionaries 1779 @return: B{Properties}: 1780 - path: (string) where the property is defined 1781 - type: (string) type of zproperty it is 1782 - options: (Array) available options for the zproperty 1783 - value (Array) value of the zproperty 1784 - valueAsString (string) 1785 """ 1786 facade = self._getFacade() 1787 data = facade.getConnectionInfo(uid) 1788 return DirectResponse.succeed(data=Zuul.marshal(data))
1789 1790 @serviceConnectionError
1791 - def getModelerPluginDocStrings(self, uid):
1792 """ 1793 Given a uid returns the documentation for all the modeler plugins. 1794 """ 1795 facade = self._getFacade() 1796 data = facade.getModelerPluginDocStrings(uid) 1797 return DirectResponse.succeed(data=Zuul.marshal(data))
1798
1799 - def addIpRouteEntry(self, uid, dest='', routemask='', nexthopid='', interface='', 1800 routeproto='', routetype='', userCreated=True):
1801 """ 1802 Adds an Ip Route Entry to this device 1803 """ 1804 facade = self._getFacade() 1805 data = facade.addIpRouteEntry(uid, dest, routemask, nexthopid, interface, 1806 routeproto, routetype, userCreated) 1807 return DirectResponse.succeed(data=Zuul.marshal(data))
1808
1809 - def addIpInterface(self, uid, newId, userCreated=True):
1810 """ 1811 Adds an Ip Interface 1812 """ 1813 facade = self._getFacade() 1814 data = facade.addIpInterface(uid, newId, userCreated) 1815 return DirectResponse.succeed(data=Zuul.marshal(data))
1816
1817 - def addOSProcess(self, uid, newClassName, example, userCreated=True):
1818 """ 1819 Adds an os processes 1820 """ 1821 facade = self._getFacade() 1822 data = facade.addOSProcess(uid, newClassName, example, userCreated) 1823 return DirectResponse.succeed(data=Zuul.marshal(data))
1824
1825 - def addFileSystem(self, uid, newId, userCreated=True):
1826 """ 1827 Adds an Ip Interface 1828 """ 1829 facade = self._getFacade() 1830 data = facade.addFileSystem(uid, newId, userCreated) 1831 return DirectResponse.succeed(data=Zuul.marshal(data))
1832
1833 - def addIpService(self, uid, newClassName, protocol, userCreated=True):
1834 """ 1835 Adds an Ip Service 1836 """ 1837 facade = self._getFacade() 1838 data = facade.addIpService(uid, newClassName, protocol, userCreated) 1839 return DirectResponse.succeed(data=Zuul.marshal(data))
1840 1841
1842 - def addWinService(self, uid, newClassName, userCreated=True):
1843 """ 1844 Adds an Ip Service 1845 """ 1846 facade = self._getFacade() 1847 data = facade.addWinService(uid, newClassName, userCreated) 1848 return DirectResponse.succeed(data=Zuul.marshal(data))
1849
1850 - def getSoftware(self, uid, keys=None):
1851 1852 facade = self._getFacade() 1853 software = facade.getSoftware(uid) 1854 return DirectResponse(data=Zuul.marshal(software, keys))
1855
1856 - def getOverriddenObjectsList(self, uid, propname, relName):
1857 """ 1858 returns a list of Overridden Objects and properties for this context 1859 """ 1860 facade = self._getFacade() 1861 data = facade.getOverriddenObjectsList(uid, propname, relName) 1862 return DirectResponse.succeed(data=Zuul.marshal(data))
1863
1864 - def getOverriddenObjectsParent(self, uid, propname=''):
1865 """ 1866 returns the base of the Overridden Objects 1867 """ 1868 facade = self._getFacade() 1869 data = facade.getOverriddenObjectsParent(uid, propname) 1870 return DirectResponse.succeed(data=Zuul.marshal(data))
1871
1872 - def getOverriddenZprops(self, uid, all=True, pfilt=''):
1873 """ 1874 returns a list of zProperty values for the overridden objects 1875 """ 1876 facade = self._getFacade() 1877 data = facade.getOverriddenZprops(uid, all) 1878 return DirectResponse.succeed(data=Zuul.marshal(data))
1879
1880 - def getGraphDefintionsForComponents(self, uid):
1881 facade = self._getFacade() 1882 data = facade.getGraphDefinitionsForComponent(uid) 1883 return DirectResponse.succeed(data=Zuul.marshal(data))
1884
1885 - def getComponentGraphs(self, uid, meta_type, graphId, allOnSame=False):
1886 """ 1887 Returns the graph denoted by graphId for every component in 1888 device (uid) with the meta_type meta_type 1889 """ 1890 facade = self._getFacade() 1891 data = facade.getComponentGraphs(uid, meta_type, graphId, allOnSame=allOnSame) 1892 return DirectResponse.succeed(data=Zuul.marshal(data))
1893
1894 - def getDevTypes(self, uid, filter=None):
1895 """ 1896 Returns a list of devtypes for the wizard 1897 """ 1898 facade = self._getFacade() 1899 data = facade.getDevTypes(uid) 1900 return DirectResponse.succeed(data=Zuul.marshal(data))
1901