class EC2Zone(AWSComponent): ''' Model class for EC2Zone. ''' meta_type = portal_type = 'EC2Zone' state = None _properties = AWSComponent._properties + ({ 'id': 'state', 'type': 'string' }, ) _relations = AWSComponent._relations + ( ('region', ToOne(ToManyCont, MODULE_NAME['EC2Region'], 'zones')), ('instances', ToMany(ToOne, MODULE_NAME['EC2Instance'], 'zone')), ('volumes', ToMany(ToOne, MODULE_NAME['EC2Volume'], 'zone')), ('vpc_subnets', ToMany(ToOne, MODULE_NAME['EC2VPCSubnet'], 'zone')), ) def getRegionId(self): return self.region().id def getInstanceIds(self): return sorted(self.instances.objectIds()) def setInstanceIds(self, ids): updateToMany(relationship=self.instances, root=self.region().instances, type_=CLASS_NAME['EC2Instance'], ids=ids) def getVolumeIds(self): return sorted(self.volumes.objectIds()) def setVolumeIds(self, ids): updateToMany(relationship=self.volumes, root=self.region().volumes, type_=CLASS_NAME['EC2Volumes'], ids=ids) def getVPCSubnetIds(self): return sorted(self.vpc_subnets.objectIds()) def setVPCSubnetIds(self, ids): updateToMany(relationship=self.vpc_subnets, root=self.region().vpc_subnets, type_=CLASS_NAME['EC2VPCSubnets'], ids=ids)
class ComponentGroup(ComponentOrganizer): """ ComponentGroup is a Component Group Organizer that allows generic component groupings. """ # Organizer configuration dmdRootName = "ComponentGroups" portal_type = meta_type = event_key = 'ComponentGroup' event_key = "ComponentGroup" _relations = ComponentOrganizer._relations + ( ("components", ToMany(ToMany, "Products.ZenModel.DeviceComponent", "componentGroups")), ) def getComponents(self): return [comp.primaryAq() for comp in self.components()] def getSubComponents(self): cat = IModelCatalogTool(self) # @TODO: Can we avoid NOTs ? query = Eq('objectImplements', 'Products.ZenModel.DeviceComponent.DeviceComponent') brains = cat.search(query=query) children = [] for brain in brains: try: children.append(brain.getObject()) except: pass return children
class Flavor(DeviceComponent, ManagedEntity): meta_type = portal_type = "OpenStackFlavor" flavorId = None # performance1-1 flavorRAM = None # Stored as bytes flavorDisk = None # Stored as bytes _properties = ManagedEntity._properties + ( { 'id': 'flavorId', 'type': 'string', 'mode': '' }, { 'id': 'flavorRAM', 'type': 'int', 'mode': '' }, { 'id': 'flavorDisk', 'type': 'int', 'mode': '' }, ) _relations = ManagedEntity._relations + ( ( 'endpoint', ToOne( ToManyCont, 'ZenPacks.zenoss.OpenStack.Endpoint.Endpoint', 'flavors', ), ), ( 'servers', ToMany( ToOne, 'ZenPacks.zenoss.OpenStack.Server.Server', 'flavor', ), ), ) factory_type_information = ({ 'actions': ({ 'id': 'perfConf', 'name': 'Template', 'action': 'objTemplates', 'permissions': (ZEN_CHANGE_DEVICE, ), }, ), }, ) # Query for events by id instead of name. event_key = "ComponentId" def device(self): return self.endpoint()
class EC2InstanceType(DeviceComponent, ManagedEntity): """ A DMD Device that represents a group of VMware hosts that can run virtual devices. """ meta_type = "EC2InstanceType" instLink = "" _properties = ({'id': 'instLink', 'type': 'string', 'mode': 'w'}, ) _relations = ( ('instances', ToMany(ToOne, "ZenPacks.zenoss.ZenAWS.EC2Instance", "instanceType")), ('manager', ToOne(ToManyCont, "ZenPacks.zenoss.ZenAWS.EC2Manager", "instanceTypes")), ) factory_type_information = ({ 'immediate_view': 'ec2InstanceTypeStatus', 'actions': ( { 'id': 'status', 'name': 'Status', 'action': 'ec2InstanceTypeStatus', 'permissions': (ZEN_VIEW, ) }, { 'id': 'events', 'name': 'Events', 'action': 'viewEvents', 'permissions': (ZEN_VIEW, ) }, { 'id': 'perfConf', 'name': 'Template', 'action': 'objTemplates', 'permissions': ("Change Device", ) }, ) }, ) def device(self): return self.manager() def name(self): return self.getId() def updateFromDict(self, propDict): for k, v in propDict.items(): setattr(self, k, v)
class StorageDomain(BaseComponent): meta_type = portal_type = "oVirtStorageDomain" storagedomain_type = None storage_type = None storage_format = None status = None _properties = BaseComponent._properties + ( {'id': 'storagedomain_type', 'type': 'string', 'mode': 'w'}, {'id': 'storage_type', 'type': 'string', 'mode': 'w'}, {'id': 'storage_format', 'type': 'string', 'mode': 'w'}, {'id': 'status', 'type': 'string', 'mode': 'w'}, ) _relations = BaseComponent._relations + ( ('system', ToOne(ToManyCont, 'ZenPacks.zenoss.oVirt.System.System', 'storagedomains') ), ('disks', ToManyCont(ToOne, 'ZenPacks.zenoss.oVirt.VmDisk.VmDisk', 'storagedomains') ), ('datacenters', ToMany(ToMany, 'ZenPacks.zenoss.oVirt.DataCenter.DataCenter', 'storagedomains') ), ) def device(self): return self.system() def setDatacenterId(self, ids): new_ids = set(ids) current_ids = set(x.id for x in self.datacenters()) for id_ in new_ids.symmetric_difference(current_ids): datacenter = self.device().datacenters._getOb(id_) if datacenter: if id_ in new_ids: self.datacenters.addRelation(datacenter) else: self.datacenters.removeRelation(datacenter) notify(IndexingEvent(datacenter, 'path', False)) def getDatacenterId(self): return sorted([x.id for x in self.datacenters()]) def getIconPath(self): return icon_for(self.device(), 'storage-domain')
class DataCenter(BaseComponent): meta_type = portal_type = "oVirtDataCenter" description = None storage_type = None storage_format = None status = None _properties = BaseComponent._properties + ( { 'id': 'description', 'type': 'string', 'mode': 'w' }, { 'id': 'storage_type', 'type': 'string', 'mode': 'w' }, { 'id': 'storage_format', 'type': 'string', 'mode': 'w' }, { 'id': 'status', 'type': 'string', 'mode': 'w' }, ) _relations = BaseComponent._relations + ( ('system', ToOne(ToManyCont, 'ZenPacks.zenoss.oVirt.System.System', 'datacenters')), ('clusters', ToManyCont(ToOne, 'ZenPacks.zenoss.oVirt.Cluster.Cluster', 'datacenter')), ('storagedomains', ToMany(ToMany, 'ZenPacks.zenoss.oVirt.StorageDomain.StorageDomain', 'datacenters')), ) def device(self): return self.system() def getIconPath(self): return icon_for(self.device(), 'data-center')
class EC2VPC(AWSComponent): ''' Model class for EC2VPC. ''' meta_type = portal_type = 'EC2VPC' cidr_block = None state = None collector = None _properties = AWSComponent._properties + ( { 'id': 'cidr_block', 'type': 'string' }, { 'id': 'state', 'type': 'string' }, { 'id': 'collector', 'type': 'string' }, ) _relations = AWSComponent._relations + ( ('region', ToOne(ToManyCont, MODULE_NAME['EC2Region'], 'vpcs')), ('vpc_subnets', ToMany(ToOne, MODULE_NAME['EC2VPCSubnet'], 'vpc')), ) def getRegionId(self): return self.region().id def getVPCSubnetIds(self): return sorted(self.vpc_subnets.objectIds()) def setVPCSubnetIds(self, ids): updateToMany(relationship=self.vpc_subnets, root=self.region().vpc_subnets, type_=CLASS_NAME['EC2VPCSubnets'], ids=ids)
class TeamInterface(IpInterface): meta_type = portal_type = 'WinTeamInterface' _relations = IpInterface._relations + ( ('teaminterfaces', ToMany(ToOne, 'ZenPacks.zenoss.Microsoft.Windows.Interface', 'teaminterface')), ) def monitored(self): ''' Return the monitored status of this component. Overridden from IpInterface to prevent monitoring administratively down interfaces. ''' return self.monitor and self.adminStatus == 1 def setInterfaces(self, ids): new_ids = set(ids) current_ids = set(x.id for x in self.teaminterfaces()) for id_ in new_ids.symmetric_difference(current_ids): interface = self.device().os.interfaces._getOb(id_, None) if interface: if id_ in new_ids: self.teaminterfaces.addRelation(interface) else: self.teaminterfaces.removeRelation(interface) notify(IndexingEvent(interface, 'path', False)) # For componentSearch. Would be nice if we could target # idxs=['getAllPaths'], but there's a chance that it won't # exist yet. interface.index_object() def getInterfaces(self): return sorted([x.id for x in self.teaminterfaces()])
class UserSettings(ZenModelRM): """zenoss user folder has users preferences. """ implements(IProvidesEmailAddresses, IProvidesPagerAddresses, IGloballyIdentifiable) meta_type = "UserSettings" sub_meta_types = ("ActionRule",) email = "" pager = "" defaultPageSize = 40 defaultEventPageSize = 30 defaultAdminRole = "ZenUser" oncallStart = 0 oncallEnd = 0 escalationMinutes = 0 dashboardState = '' netMapStartObject = '' eventConsoleRefresh = True zenossNetUser = '' zenossNetPassword = '' _properties = ZenModelRM._properties + ( {'id':'email', 'type':'string', 'mode':'w'}, {'id':'pager', 'type':'string', 'mode':'w'}, {'id':'defaultPageSize', 'type':'int', 'mode':'w'}, {'id':'defaultEventPageSize', 'type':'int', 'mode':'w'}, {'id':'defaultAdminRole', 'type':'string', 'mode':'w'}, {'id':'oncallStart', 'type':'int', 'mode':'w'}, {'id':'oncallEnd', 'type':'int', 'mode':'w'}, {'id':'escalationMinutes', 'type':'int', 'mode':'w'}, {'id':'dashboardState', 'type':'string', 'mode':'w'}, {'id':'netMapStartObject', 'type':'string', 'mode':'w'}, {'id':'eventConsoleRefresh', 'type':'boolean', 'mode':'w'}, {'id':'zenossNetUser', 'type':'string', 'mode':'w'}, {'id':'zenossNetPassword', 'type':'string', 'mode':'w'}, ) _relations = ( ("adminRoles", ToMany(ToOne, "Products.ZenModel.AdministrativeRole", "userSetting")), ("messages", ToManyCont(ToOne, "Products.ZenWidgets.PersistentMessage.PersistentMessage", "messageQueue")), ) # Screen action bindings (and tab definitions) factory_type_information = ( { 'immediate_view' : 'editUserSettings', 'actions' : ( {'name' : 'Edit', 'action' : 'editUserSettings', 'permissions' : (ZEN_CHANGE_SETTINGS,), }, {'name' : 'Administered Objects', 'action' : 'administeredDevices', 'permissions' : (ZEN_CHANGE_ADMIN_OBJECTS,) }, ) }, ) security = ClassSecurityInfo() def hasNoGlobalRoles(self): """This user doesn't have global roles. Used to limit access """ return self.id != 'admin' and len(self.getUserRoles()) == 0 def getUserRoles(self): """Get current roles for this user. """ user = self.getUser(self.id) if user: # This call will create GroupSettings objects for any externally- # sourced groups. self.getAllAdminRoles() return filter(rolefilter, user.getRoles()) return [] def getUserGroupSettingsNames(self): """Return group settings objects for user """ user = self.getUser(self.id) if user: return self.acl_users._getGroupsForPrincipal(user) return () security.declareProtected(ZEN_CHANGE_SETTINGS, 'updatePropsFromDict') def updatePropsFromDict(self, propdict): props = self.propertyIds() for k, v in propdict.items(): if k in props: setattr(self,k,v) def iseditable(self): """Can the current user edit this settings object. """ currentUser = getSecurityManager().getUser() # Managers can edit any users' settings. if currentUser.has_role("Manager"): return True # thisUser can be None if the plugin that created it is inactive. thisUser = self.acl_users.getUser(self.id) if thisUser is None: return False # ZenManagers can edit any users' settings except for Managers. if currentUser.has_role("ZenManager") \ and not thisUser.has_role("Manager"): return True # Users can edit their own settings. if thisUser.getUserName() == currentUser.getUserName(): return True return False security.declareProtected(ZEN_CHANGE_SETTINGS, 'manage_resetPassword') def manage_resetPassword(self): """ Reset a password. """ email = self.email.strip() if not email: messaging.IMessageSender(self).sendToBrowser( 'Password Reset Failed', 'Cannot send password reset email; user has no'+ ' email address.', priority=messaging.WARNING ) return self.callZenScreen(self.REQUEST) newpw = self.generatePassword() body = """ Your Zenoss password has been reset at %s's request. Your new password is: %s """ % (self.getUser().getId(), newpw) msg = MIMEText(body) msg['Subject'] = 'Zenoss Password Reset Request' msg['From'] = self.dmd.getEmailFrom() msg['To'] = email msg['Date'] = DateTime().rfc822() result, errorMsg = Utils.sendEmail(msg, self.dmd.smtpHost, self.dmd.smtpPort, self.dmd.smtpUseTLS, self.dmd.smtpUser, self.dmd.smtpPass) if result: userManager = self.acl_users.userManager try: userManager.updateUserPassword(self.id, newpw) except KeyError: self.getPhysicalRoot().acl_users.userManager.updateUserPassword( self.id, newpw) messaging.IMessageSender(self).sendToBrowser( 'Password reset', 'An email with a new password has been sent.' ) audit('UI.User.ResetPassword', username=self.id) loggedInUser = self.REQUEST['AUTHENTICATED_USER'] # we only want to log out the user if it's *their* password # they've changed, not, for example, if the admin user is # changing another user's password if loggedInUser.getUserName() == self.id: self.acl_users.logout(self.REQUEST) else: messaging.IMessageSender(self).sendToBrowser( 'Password reset failed', 'Unable to send password reset email: %s' % errorMsg, priority=messaging.WARNING ) return self.callZenScreen(self.REQUEST) security.declareProtected(ZEN_CHANGE_SETTINGS, 'manage_editUserSettings') def manage_editUserSettings(self, oldpassword=None, password=None, sndpassword=None, roles=None, groups=None, domains=None, REQUEST=None, **kw): """Update user settings. """ # get the user object; return if no user user = self.acl_users.getUser(self.id) if not user: user = self.getPhysicalRoot().acl_users.getUser(self.id) if not user: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'User %s not found.' % self.id, priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return # Verify existing password curuser = self.getUser().getId() if not oldpassword or not self.ZenUsers.authenticateCredentials( curuser, oldpassword): if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'Confirmation password is empty or invalid. Please'+ ' confirm your password for security reasons.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: raise ValueError("Current password is incorrect.") # update role info roleManager = self.acl_users.roleManager origRoles = filter(rolefilter, user.getRoles()) if not self.has_role('Manager') and roles and 'Manager' in roles: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'Only Managers can make more Managers.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return if not self.has_role('Manager') and origRoles and \ 'Manager' in origRoles: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'Only Managers can modify other Managers.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return # if there's a change, then we need to update # TODO: Record all the non-password values. #updates = dict((k,v) for k,v in kw.items() if 'password' not in k.lower()) updates = {} # update user roles if roles is None: roles = () origRolesSet = set(origRoles) rolesSet = set(roles) if rolesSet != origRolesSet and self.isManager(): # get roles to remove and then remove them removeRoles = origRolesSet - rolesSet for role in removeRoles: try: roleManager.removeRoleFromPrincipal(role, self.id) except KeyError: # User doesn't actually have that role; ignore pass # get roles to add and then add them addRoles = rolesSet - origRolesSet for role in addRoles: roleManager.assignRoleToPrincipal(role, self.id) updates['roles'] = roles # update group info if groups is None: groups = () groupManager = self.acl_users.groupManager origGroupsSet = set(groupManager.getGroupsForPrincipal(user)) groupsSet = set(groups) # if there's a change, then we need to update if groupsSet != origGroupsSet and self.isManager(): # get groups to remove and then remove them removeGroups = origGroupsSet - groupsSet for groupid in removeGroups: groupManager.removePrincipalFromGroup(user.getId(), groupid) # get groups to add and then add them addGroups = groupsSet - origGroupsSet for groupid in addGroups: try: groupManager.addPrincipalToGroup(user.getId(), groupid) except KeyError: # This can occur if the group came from an external source. pass updates['groups'] = groups # we're not managing domains right now if domains: msg = 'Zenoss does not currently manage domains for users.' raise NotImplementedError(msg) # update Zenoss user folder settings if REQUEST: kw = REQUEST.form self.manage_changeProperties(**kw) # update password info if self.id=='admin': userManager = self.getPhysicalRoot().acl_users.userManager else: userManager = self.acl_users.userManager if password: if password.find(':') >= 0: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'Passwords cannot contain a ":". Password not updated.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: raise ValueError("Passwords cannot contain a ':' ") elif password != sndpassword: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'Passwords did not match. Password not updated.', priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: raise ValueError("Passwords don't match") else: try: userManager.updateUserPassword(self.id, password) updates['password'] = '******' except KeyError: self.getPhysicalRoot().acl_users.userManager.updateUserPassword( self.id, password) if REQUEST: loggedInUser = REQUEST['AUTHENTICATED_USER'] # we only want to log out the user if it's *their* password # they've changed, not, for example, if the admin user is # changing another user's password if loggedInUser.getUserName() == self.id: self.acl_users.logout(REQUEST) # finish up if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Settings Saved', Time.SaveMessage() ) audit('UI.User.Edit', username=self.id, data_=updates) return self.callZenScreen(REQUEST) else: return user security.declareProtected(ZEN_CHANGE_ALERTING_RULES, 'manage_addActionRule') @deprecated def manage_addActionRule(self, id=None, REQUEST=None): """Add an action rule to this object. """ if id: ar = ActionRule(id) self._setObject(id, ar) ar = self._getOb(id) user = getSecurityManager().getUser() # current user userid = user.getId() if userid != self.id: # if we are not the current user userid = self.id user = self.getUser(userid) ar.changeOwnership(user) # make us the owner of it ar.manage_setLocalRoles(userid, ("Owner",)) if REQUEST: return self.callZenScreen(REQUEST) def getActionRules(self): return self.objectValues(spec=ActionRule.meta_type) security.declareProtected(ZEN_CHANGE_EVENT_VIEWS, 'manage_addCustomEventView') @deprecated def manage_addCustomEventView(self, id=None, REQUEST=None): """Add a custom event view to this object. """ if id: ar = CustomEventView(id) self._setObject(id, ar) ar = self._getOb(id) user = getSecurityManager().getUser() userid = user.getId() if userid != self.id: userid = self.id user = self.getUser(userid) ar.changeOwnership(user) ar.manage_setLocalRoles(userid, ("Owner",)) if REQUEST: return self.callZenScreen(REQUEST) security.declareProtected(ZEN_CHANGE_ADMIN_OBJECTS, 'manage_addAdministrativeRole') def manage_addAdministrativeRole(self, name=None, type='device', role=None, guid=None, uid=None, REQUEST=None): "Add a Admin Role to the passed object" unused(role) mobj = None if guid or uid: # look up our object by either guid or uid if guid: manager = IGUIDManager(self.dmd) mobj = manager.getObject(guid) elif uid: mobj = self.unrestrictedTraverse(uid) else: # use magic to look up our object if not name: name = REQUEST.deviceName if type == 'device': mobj =self.getDmdRoot("Devices").findDevice(name) else: try: root = type.capitalize()+'s' if type == "deviceClass": mobj = self.getDmdRoot("Devices").getOrganizer(name) else: mobj = self.getDmdRoot(root).getOrganizer(name) except KeyError: pass if not mobj: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', "%s %s not found"%(type.capitalize(),name), priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return roleNames = [ r.id for r in mobj.adminRoles() ] if self.id in roleNames: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', (("Administrative Role for %s %s " "for user %s already exists.") % (type, name, self.id)), priority=messaging.WARNING ) return self.callZenScreen(REQUEST) else: return mobj.manage_addAdministrativeRole(self.id) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Role Added', ("Administrative Role for %s %s for user %s added" % (type, name, self.id)) ) audit('UI.User.AddAdministrativeRole', username=self.id, data_={mobj.meta_type:mobj.getPrimaryId()}) return self.callZenScreen(REQUEST) security.declareProtected(ZEN_CHANGE_ADMIN_OBJECTS, 'manage_editAdministrativeRoles') def manage_editAdministrativeRoles(self, ids=(), role=(), REQUEST=None): """Edit list of admin roles. """ if isinstance(ids, basestring): ids = [ids] role = [role] else: ids = list(ids) for ar in self.adminRoles(): mobj = ar.managedObject() try: i = ids.index(mobj.managedObjectName()) except ValueError: continue mobj = mobj.primaryAq() mobj.manage_editAdministrativeRoles(self.id, role[i]) if REQUEST: audit('UI.User.EditAdministrativeRole', username=self.id, data_={mobj.meta_type:mobj.getPrimaryId()}, role=role[i]) if REQUEST: if ids: messaging.IMessageSender(self).sendToBrowser( 'Roles Updated', "Administrative roles were updated." ) return self.callZenScreen(REQUEST) security.declareProtected(ZEN_CHANGE_ADMIN_OBJECTS, 'manage_deleteAdministrativeRole') def manage_deleteAdministrativeRole(self, delids=(), REQUEST=None): "Delete admin roles of objects." if isinstance(delids, basestring): delids = [delids] for ar in self.adminRoles(): mobj = ar.managedObject() if mobj.managedObjectName() not in delids: continue mobj = mobj.primaryAq() mobj.manage_deleteAdministrativeRole(self.id) if REQUEST: audit('UI.User.DeleteAdministrativeRole', username=self.id, data_={mobj.meta_type:mobj.getPrimaryId()}) if REQUEST: if delids: messaging.IMessageSender(self).sendToBrowser( 'Roles Deleted', "Administrative roles were deleted." ) return self.callZenScreen(REQUEST) security.declareProtected(ZEN_CHANGE_SETTINGS, 'getAllAdminRoles') def getAllAdminRoles(self): """Return all admin roles for this user and its groups """ ars = self.adminRoles() for group in self.getUser().getGroups(): gs = self.getGroupSettings(group) ars.extend(gs.adminRoles()) return ars security.declareProtected(ZEN_CHANGE_SETTINGS, 'manage_emailTest') def manage_emailTest(self, REQUEST=None): ''' Send a test email to the given userid. ''' destSettings = self.getUserSettings(self.getId()) destAddresses = destSettings.getEmailAddresses() msg = None if destAddresses: fqdn = socket.getfqdn() thisUser = self.getUser() srcId = thisUser.getId() self.getUserSettings(srcId) srcAddress = self.dmd.getEmailFrom() # Read body from file probably body = ('This is a test message sent by %s' % srcId + ' from the Zenoss installation on %s.' % fqdn) emsg = MIMEText(body) emsg['Subject'] = 'Zenoss Email Test' emsg['From'] = srcAddress emsg['To'] = ', '.join(destAddresses) emsg['Date'] = DateTime().rfc822() result, errorMsg = Utils.sendEmail(emsg, self.dmd.smtpHost, self.dmd.smtpPort, self.dmd.smtpUseTLS, self.dmd.smtpUser, self.dmd.smtpPass) if result: msg = 'Test email sent to %s' % ', '.join(destAddresses) else: msg = 'Test failed: %s' % errorMsg else: msg = 'Test email not sent, user has no email address.' if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Email Test', msg.replace("'", "\\'") ) return self.callZenScreen(REQUEST) else: return msg security.declareProtected(ZEN_CHANGE_SETTINGS, 'manage_pagerTest') def manage_pagerTest(self, REQUEST=None): ''' Send a test page ''' destSettings = self.getUserSettings(self.getId()) destPagers = [ x.strip() for x in (destSettings.getPagerAddresses() or []) ] msg = None fqdn = socket.getfqdn() srcId = self.getUser().getId() testMsg = ('Test sent by %s' % srcId + ' from the Zenoss installation on %s.' % fqdn) for destPager in destPagers: result, errorMsg = Utils.sendPage(destPager, testMsg, self.dmd.pageCommand) if result: msg = 'Test page sent to %s' % ', '.join(destPagers) else: msg = 'Test failed: %s' % errorMsg break if not destPagers: msg = 'Test page not sent, user has no pager number.' if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Pager Test', msg) return self.callZenScreen(REQUEST) else: return msg def exportXmlHook(self, ofile, ignorerels): """patch to export all user configuration """ for o in self.objectValues(): if hasattr(aq_base(o), 'exportXml'): o.exportXml(ofile, ignorerels) def getPagerAddresses(self): if self.pager and self.pager.strip(): return [self.pager.strip()] return [] def getEmailAddresses(self): if self.email and self.email.strip(): return [self.email] return [] def isLoggedInUser(self): loggedinUser = self.ZenUsers.getUserSettings() return loggedinUser.id == self.id def getDotNetSession(self): """ Use the Zenoss.net credentials associated with this user to log in to a Zenoss.net session. """ session = DotNetCommunication.getDotNetSession( self.zenossNetUser, self.zenossNetPassword) return session def removeAdminRoles(self): """ Call before deleting a user or group this will remove this user/group from the list of admin objects for everything that the object adminstered before. This prevents broken relationships """ for role in self.getAllAdminRoles(): obj = role.managedObject().primaryAq() obj.manage_deleteAdministrativeRole(self.id)
class Image(DeviceComponent, ManagedEntity): meta_type = portal_type = "OpenStackImage" imageId = None # 346eeba5-a122-42f1-94e7-06cb3c53f690 imageStatus = None # ACTIVE imageCreated = None # 010-09-17T07:19:20-05:00 imageUpdated = None # 010-09-17T07:19:20-05:00 _properties = ManagedEntity._properties + ( { 'id': 'imageId', 'type': 'string', 'mode': '' }, { 'id': 'imageStatus', 'type': 'string', 'mode': '' }, { 'id': 'imageCreated', 'type': 'string', 'mode': '' }, { 'id': 'imageUpdated', 'type': 'string', 'mode': '' }, ) _relations = ManagedEntity._relations + ( ( 'endpoint', ToOne( ToManyCont, 'ZenPacks.zenoss.OpenStack.Endpoint.Endpoint', 'images', ), ), ( 'servers', ToMany( ToOne, 'ZenPacks.zenoss.OpenStack.Server.Server', 'image', ), ), ) factory_type_information = ({ 'actions': ({ 'id': 'perfConf', 'name': 'Template', 'action': 'objTemplates', 'permissions': (ZEN_CHANGE_DEVICE, ), }, ), }, ) # Query for events by id instead of name. event_key = "ComponentId" def device(self): return self.endpoint()
class IpAddress(ManagedEntity, Layer3Linkable): """IpAddress object""" zope.interface.implements(IIndexed) event_key = portal_type = meta_type = 'IpAddress' default_catalog = 'ipSearch' version = 4 _properties = ( { 'id': 'netmask', 'type': 'string', 'mode': 'w', 'setter': 'setNetmask' }, { 'id': 'ptrName', 'type': 'string', 'mode': 'w' }, { 'id': 'version', 'type': 'int', 'mode': 'w' }, ) _relations = ManagedEntity._relations + ( ("network", ToOne(ToManyCont, "Products.ZenModel.IpNetwork", "ipaddresses")), ("interface", ToOne(ToMany, "Products.ZenModel.IpInterface", "ipaddresses")), ("clientroutes", ToMany(ToOne, "Products.ZenModel.IpRouteEntry", "nexthop")), ) factory_type_information = ({ 'id': 'IpAddress', 'meta_type': 'IpAddress', 'description': """Ip Address Class""", 'icon': 'IpAddress_icon.gif', 'product': 'ZenModel', 'factory': 'manage_addIpAddress', 'immediate_view': 'viewIpAddressOverview', 'actions': ({ 'id': 'overview', 'name': 'Overview', 'action': 'viewIpAddressOverview', 'permissions': ("View", ) }, ) }, ) security = ClassSecurityInfo() def __init__(self, id, netmask=24): checkip(id) ManagedEntity.__init__(self, ipwrap(id)) ipobj = IPAddress(ipunwrap_strip(id)) if ipobj.version == 6: # No user-definable subnet masks for IPv6 netmask = 64 self._netmask = maskToBits(netmask) self.ptrName = None self.title = ipunwrap(id) self.version = ipobj.version def setPtrName(self): try: data = socket.gethostbyaddr(ipunwrap(self.id)) if data: self.ptrName = data[0] except socket.error, e: self.ptrName = "" log.warn("%s: %s", self.title, e)
class VMAppliance(PooledComponent): ''' Model class for VMAppliance. Also known as vApp. ''' class_label = 'vApp' class_plural_label = 'vApps' meta_type = portal_type = 'XenServerVMAppliance' allowed_operations = None name_description = None name_label = None _properties = PooledComponent._properties + ( { 'id': 'allowed_operations', 'label': 'Allowed Operations', 'type': 'lines', 'mode': 'w' }, { 'id': 'name_description', 'label': 'Description', 'type': 'string', 'mode': 'w' }, { 'id': 'name_label', 'label': 'Label', 'type': 'string', 'mode': 'w' }, ) _relations = PooledComponent._relations + ( ('endpoint', ToOne(ToManyCont, MODULE_NAME['Endpoint'], 'vmappliances')), ('vms', ToMany(ToOne, MODULE_NAME['VM'], 'vmappliance')), ) @classmethod def objectmap(cls, ref, properties): ''' Return an ObjectMap given XenAPI vm_appliance ref and properties. ''' if not properties: return { 'relname': 'vmappliances', 'id': id_from_ref(ref), } title = properties.get('name_label') or properties['uuid'] return { 'relname': 'vmappliances', 'id': id_from_ref(ref), 'title': title, 'xenapi_ref': ref, 'xenapi_uuid': properties.get('uuid'), 'allowed_operations': properties.get('allowed_operations'), 'name_description': properties.get('name_description'), 'name_label': properties.get('name_label'), 'setVMs': ids_from_refs(properties.get('VMs', [])), } def getVMs(self): ''' Return a sorted list of related VM ids. Aggregate. Used by modeling. ''' return sorted([vm.id for vm in self.vms.objectValuesGen()]) def setVMs(self, vm_ids): ''' Update VM relationship given ids. Used by modeling. ''' updateToMany(relationship=self.vms, root=self.device(), type_=CLASS_NAME['VM'], ids=vm_ids) def xenrrd_prefix(self): ''' Return prefix under which XenServer stores RRD data about this component. ''' # This is a guess at future support. XenServer 6.2 doesn't have # any RRD data for VMAppliances. if self.xenapi_uuid: return ('vmappliance', self.xenapi_uuid, '') def getIconPath(self): ''' Return URL to icon representing objects of this class. ''' return '/++resource++xenserver/img/virtual-server.png'
class SR(PooledComponent): ''' Model class for SR. Also known as Storage Repository. ''' class_label = 'Storage Repository' class_plural_label = 'Storage Repositories' meta_type = portal_type = 'XenServerSR' allowed_operations = None content_type = None local_cache_enabled = None name_description = None name_label = None physical_size = None shared = None sm_type = None sr_type = None _properties = PooledComponent._properties + ( { 'id': 'allowed_operations', 'label': 'Allowed Operations', 'type': 'lines', 'mode': 'w' }, { 'id': 'content_type', 'label': 'Content Type', 'type': 'string', 'mode': 'w' }, { 'id': 'local_cache_enabled', 'label': 'Local Cache Enabled', 'type': 'boolean', 'mode': 'w' }, { 'id': 'name_description', 'label': 'Description', 'type': 'string', 'mode': 'w' }, { 'id': 'name_label', 'label': 'Label', 'type': 'string', 'mode': 'w' }, { 'id': 'physical_size', 'label': 'Physical Size', 'type': 'int', 'mode': 'w' }, { 'id': 'shared', 'label': 'Shared', 'type': 'boolean', 'mode': 'w' }, { 'id': 'sm_type', 'label': 'SM Type', 'type': 'string', 'mode': 'w' }, { 'id': 'sr_type', 'label': 'Type', 'type': 'string', 'mode': 'w' }, ) _relations = PooledComponent._relations + ( ('endpoint', ToOne( ToManyCont, MODULE_NAME['Endpoint'], 'srs', )), ('vdis', ToManyCont( ToOne, MODULE_NAME['VDI'], 'sr', )), ('pbds', ToMany( ToOne, MODULE_NAME['PBD'], 'sr', )), ('default_for_pools', ToMany(ToOne, MODULE_NAME['Pool'], 'default_sr')), ('suspend_image_for_pools', ToMany(ToOne, MODULE_NAME['Pool'], 'suspend_image_sr')), ('crash_dump_for_pools', ToMany(ToOne, MODULE_NAME['Pool'], 'crash_dump_sr')), ('suspend_image_for_hosts', ToMany(ToOne, MODULE_NAME['Host'], 'suspend_image_sr')), ('crash_dump_for_hosts', ToMany(ToOne, MODULE_NAME['Host'], 'crash_dump_sr')), ('local_cache_for_hosts', ToMany(ToOne, MODULE_NAME['Host'], 'local_cache_sr')), ) @classmethod def objectmap(cls, ref, properties): ''' Return an ObjectMap given XenAPI SR ref and properties. ''' if 'uuid' not in properties: return { 'relname': 'srs', 'id': id_from_ref(ref), } title = properties.get('name_label') or properties['uuid'] sm_config = properties.get('sm_config', {}) return { 'relname': 'srs', 'id': id_from_ref(ref), 'title': title, 'xenapi_ref': ref, 'xenapi_uuid': properties.get('uuid'), 'allowed_operations': properties.get('allowed_operations'), 'content_type': properties.get('content_type'), 'local_cache_enabled': properties.get('local_cache_enabled'), 'name_description': properties.get('name_description'), 'name_label': properties.get('name_label'), 'physical_size': properties.get('physical_size'), 'shared': properties.get('shared'), 'sm_type': sm_config.get('type'), 'sr_type': properties.get('type'), 'setPBDs': ids_from_refs(properties.get('PBDs', [])) } def getPBDs(self): ''' Return a sorted list of related PBD ids. Used by modeling. ''' return sorted(x.id for x in self.pbds.objectValuesGen()) def setPBDs(self, pbd_ids): ''' Update PBD relationship given PBD ids. Used by modeling. ''' updateToMany(relationship=self.pbds, root=self.device(), type_=CLASS_NAME['PBD'], ids=pbd_ids) def getDefaultForPools(self): ''' Return a sorted list of related Pool ids. Used by modeling. ''' return sorted(x.id for x in self.default_for_pools.objectValuesGen()) def setDefaultForPools(self, pool_ids): ''' Set default_for_pools relationship by Pool id. Used by modeling. ''' updateToMany(relationship=self.default_for_pools, root=self.device(), type_=CLASS_NAME['Pool'], ids=pool_ids) def getSuspendImageForPools(self): ''' Return a sorted list of related Pool ids. Used by modeling. ''' return sorted(x.id for x in self.suspend_image_for_pools.objectValuesGen()) def setSuspendImageForPools(self, pool_ids): ''' Set suspend_image_for_pools relationship by Pool id. Used by modeling. ''' updateToMany(relationship=self.suspend_image_for_pools, root=self.device(), type_=CLASS_NAME['Pool'], ids=pool_ids) def getCrashDumpForPools(self): ''' Return a sorted list of related Pool ids. Used by modeling. ''' return sorted(x.id for x in self.crash_dump_for_pools.objectValuesGen()) def setCrashDumpForPools(self, pool_ids): ''' Set crash_dump_for_pools relationship by Pool id. Used by modeling. ''' updateToMany(relationship=self.crash_dump_for_pools, root=self.device(), type_=CLASS_NAME['Pool'], ids=pool_ids) def getSuspendImageForHosts(self): ''' Return a sorted list of related Host ids. Used by modeling. ''' return sorted(x.id for x in self.suspend_image_for_hosts.objectValuesGen()) def setSuspendImageForHosts(self, pool_ids): ''' Set suspend_image_for_hosts relationship by Host id. Used by modeling. ''' updateToMany(relationship=self.suspend_image_for_hosts, root=self.device(), type_=CLASS_NAME['Host'], ids=pool_ids) def getCrashDumpForHosts(self): ''' Return a sorted list of related Host ids. Used by modeling. ''' return sorted(x.id for x in self.crash_dump_for_hosts.objectValuesGen()) def setCrashDumpForHosts(self, pool_ids): ''' Set crash_dump_for_hosts relationship by Host id. Used by modeling. ''' updateToMany(relationship=self.crash_dump_for_hosts, root=self.device(), type_=CLASS_NAME['Host'], ids=pool_ids) def getLocalCacheForHosts(self): ''' Return a sorted list of related Host ids. Used by modeling. ''' return sorted(x.id for x in self.local_cache_for_hosts.objectValuesGen()) def setLocalCacheForHosts(self, pool_ids): ''' Set local_cache_for_hosts relationship by Host id. Used by modeling. ''' updateToMany(relationship=self.local_cache_for_hosts, root=self.device(), type_=CLASS_NAME['Host'], ids=pool_ids) def xenrrd_prefix(self): ''' Return prefix under which XenServer stores RRD data about this component. ''' # This is a guess at future support. XenServer 6.2 doesn't have # any RRD data for SRs. if self.xenapi_uuid: return ('sr', self.xenapi_uuid, '') def getIconPath(self): ''' Return URL to icon representing objects of this class. ''' return '/++resource++xenserver/img/storage-domain.png'
class Network(PooledComponent): ''' Model class for Network. ''' class_label = 'Network' class_plural_label = 'Networks' meta_type = portal_type = 'XenServerNetwork' mtu = None allowed_operations = None bridge = None default_locking_mode = None name_description = None name_label = None ipv4_begin = None ipv4_end = None is_guest_installer_network = None is_host_internal_management_network = None ipv4_netmask = None _properties = PooledComponent._properties + ( {'id': 'mtu', 'label': 'MTU', 'type': 'string', 'mode': 'w'}, {'id': 'allowed_operations', 'label': 'Allowed Operations', 'type': 'lines', 'mode': 'w'}, {'id': 'bridge', 'label': 'Bridge', 'type': 'string', 'mode': 'w'}, {'id': 'default_locking_mode', 'label': 'Default Locking Mode', 'type': 'string', 'mode': 'w'}, {'id': 'name_description', 'label': 'Description', 'type': 'string', 'mode': 'w'}, {'id': 'name_label', 'label': 'Label', 'type': 'string', 'mode': 'w'}, {'id': 'ipv4_begin', 'label': 'IPv4 Begin', 'type': 'string', 'mode': 'w'}, {'id': 'ipv4_end', 'label': 'IPv4 End', 'type': 'string', 'mode': 'w'}, {'id': 'is_guest_installer_network', 'label': 'Guest Installer Network', 'type': 'boolean', 'mode': 'w'}, {'id': 'is_host_internal_management_network', 'label': 'Host Internal Management Network', 'type': 'boolean', 'mode': 'w'}, {'id': 'ipv4_netmask', 'label': 'IPv4 Netmask', 'type': 'string', 'mode': 'w'}, ) _relations = PooledComponent._relations + ( ('endpoint', ToOne(ToManyCont, MODULE_NAME['Endpoint'], 'networks')), ('pifs', ToMany(ToOne, MODULE_NAME['PIF'], 'network')), ('vifs', ToMany(ToOne, MODULE_NAME['VIF'], 'network')), ) @classmethod def objectmap(cls, ref, properties): ''' Return an ObjectMap given XenAPI network ref and properties. ''' if 'uuid' not in properties: return { 'relname': 'networks', 'id': id_from_ref(ref), } title = properties.get('name_label') or properties['uuid'] other_config = properties.get('other_config', {}) return { 'relname': 'networks', 'id': id_from_ref(ref), 'title': title, 'xenapi_ref': ref, 'xenapi_uuid': properties.get('uuid'), 'mtu': properties.get('MTU'), 'allowed_operations': properties.get('allowed_operations'), 'bridge': properties.get('bridge'), 'default_locking_mode': properties.get('default_locking_mode'), 'name_description': properties.get('name_description'), 'name_label': properties.get('name_label'), 'ipv4_begin': other_config.get('ip_begin'), 'ipv4_end': other_config.get('ip_end'), 'is_guest_installer_network': to_boolean(other_config.get('is_guest_installer_network')), 'is_host_internal_management_network': to_boolean(other_config.get('is_host_internal_management_network')), 'ipv4_netmask': other_config.get('ipv4_netmask'), 'setPIFs': ids_from_refs(properties.get('PIFs', [])), 'setVIFs': ids_from_refs(properties.get('VIFs', [])), } def getPIFs(self): ''' Return a sorted list of ids in pifs relationship. Used by modeling. ''' return sorted(pif.id for pif in self.pifs.objectValuesGen()) def setPIFs(self, pif_ids): ''' Update pifs relationship given ids. Used by modeling. ''' updateToMany( relationship=self.pifs, root=self.device(), type_=CLASS_NAME['PIF'], ids=pif_ids) def getVIFs(self): ''' Return a sorted list of ids in vifs relationship. Used by modeling. ''' return sorted(vif.id for vif in self.vifs.objectValuesGen()) def setVIFs(self, vif_ids): ''' Update vifs relationship given ids. Used by modeling. ''' updateToMany( relationship=self.vifs, root=self.device(), type_=CLASS_NAME['VIF'], ids=vif_ids) def xenrrd_prefix(self): ''' Return prefix under which XenServer stores RRD data about this component. ''' # This is a guess at future support. XenServer 6.2 doesn't have # any RRD data for networks. if self.xenapi_uuid: return ('network', self.xenapi_uuid, '') def getIconPath(self): ''' Return URL to icon representing objects of this class. ''' return '/++resource++xenserver/img/virtual-network-interface.png'
class A10VirtualServer(A10Component): meta_type = portal_type = "A10VirtualServer" VirtualServerName = None VirtualServerAddress = None VirtualServerEnabled = 0 VirtualServerDisplayStatus = 0 VirtualServerDisplayStatusString = None VirtualServerPortNum = 0 VirtualServerPortType = 0 VirtualServerPortTypeString = None VirtualServerPortEnabled = 0 VirtualServerPortEnabledString = None VirtualServerPortServiceGroup = None VirtualServerServiceGroupList = [] VirtualServerServiceGroupObjectList = [] VirtualServerServerList = [] _properties = A10Component._properties + ( {'id':'snmpindex', 'type':'string', 'mode':''}, {'id': 'VirtualServerName', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerAddress', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerEnabled', 'type': 'int', 'mode': ''}, {'id': 'VirtualServerDisplayStatus', 'type': 'int', 'mode': ''}, {'id': 'VirtualServerDisplayStatusString', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerPortNum', 'type': 'int', 'mode': ''}, {'id': 'VirtualServerPortType', 'type': 'int', 'mode': ''}, {'id': 'VirtualServerPortTypeString', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerPortEnabled', 'type': 'int', 'mode': ''}, {'id': 'VirtualServerPortEnabledString', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerPortServiceGroup', 'type': 'string', 'mode': ''}, {'id': 'VirtualServerServiceGroupList', 'type': 'lines', 'mode': ''}, {'id': 'VirtualServerServiceGroupObjectList', 'type': 'lines', 'mode': ''}, {'id': 'VirtualServerServerList', 'type': 'lines', 'mode': ''}, ) _relations = A10Component._relations + ( ('a10Device', ToOne(ToManyCont, 'ZenPacks.community.A10.A10Device', 'a10VirtualServers', ), ), ('a10VsServiceGroups', ToMany(ToMany, 'ZenPacks.community.A10.A10ServiceGroup', 'a10SgVirtualServers', ), ), ('a10VsServers', ToMany(ToMany, 'ZenPacks.community.A10.A10Server', 'a10SVirtualServers', ), ), ) # Custom components must always implement the device method. The method # should return the device object that contains the component. def device(self): return self.a10Device() def viewName(self): """Pretty version human readable version of this object""" return self.id # use viewName as titleOrId because that method is used to display a human # readable version of the object in the breadcrumbs titleOrId = name = viewName
class Vm(BaseComponent): meta_type = portal_type = "oVirtVm" vm_type = None state = None memory = None cpu_cores = None cpu_sockets = None os_type = None os_boot = None start_time = None creation_time = None affinity = None memory_policy_guaranteed = None _properties = BaseComponent._properties + ( { 'id': 'vm_type', 'type': 'string', 'mode': 'w' }, { 'id': 'state', 'type': 'string', 'mode': 'w' }, { 'id': 'memory', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_cores', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_sockets', 'type': 'string', 'mode': 'w' }, { 'id': 'os_type', 'type': 'string', 'mode': 'w' }, { 'id': 'os_boot', 'type': 'string', 'mode': 'w' }, { 'id': 'start_time', 'type': 'string', 'mode': 'w' }, { 'id': 'creation_time', 'type': 'string', 'mode': 'w' }, { 'id': 'affinity', 'type': 'string', 'mode': 'w' }, { 'id': 'memory_policy_guaranteed', 'type': 'string', 'mode': 'w' }, ) _relations = BaseComponent._relations + ( ('cluster', ToOne(ToManyCont, 'ZenPacks.zenoss.oVirt.Cluster.Cluster', 'vms')), ('disks', ToMany(ToOne, 'ZenPacks.zenoss.oVirt.VmDisk.VmDisk', 'vm')), ('host', ToOne(ToMany, 'ZenPacks.zenoss.oVirt.Host.Host', 'vms')), ('nics', ToManyCont(ToOne, 'ZenPacks.zenoss.oVirt.VmNic.VmNic', 'vm')), ) def setHostId(self, id): for host in self.cluster().hosts(): if id == host.id: self.host.addRelation(host) notify(IndexingEvent(host, 'path', False)) return def getHostId(self): host = self.host() if host: return host.id def guest(self): macAddress = [nic.mac for nic in self.nics()] if not macAddress: return None cat = self.dmd.ZenLinkManager._getCatalog(layer=2) if cat is not None: for nic in self.nics(): if not nic.mac: continue # Use the first nic on a device, if we modelled the vm # this nic should already exist brains = cat(macaddress=nic.mac) if brains: for brain in brains: device = brain.getObject().device() if device: return device return None def device(self): return self.cluster().device() def getIconPath(self): if self.vm_type and 'server' in self.vm_type.lower(): return icon_for(self.device(), 'virtual-server') else: return icon_for(self.device(), 'virtual-desktop')
class ManagedEntity(ZenModelRM, DeviceResultInt, EventView, MetricMixin, MaintenanceWindowable): """ ManagedEntity is an entity in the system that is managed by it. Its basic property is that it can be classified by the ITClass Tree. Also has EventView and MetricMixin available. """ # list of performance multigraphs (see PerformanceView.py) # FIXME this needs to go to some new setup and doesn't work now #_mgraphs = [] # primary snmpindex for this managed entity snmpindex = 0 snmpindex_dct = {} monitor = True _properties = ( { 'id': 'snmpindex', 'type': 'string', 'mode': 'w' }, { 'id': 'monitor', 'type': 'boolean', 'mode': 'w' }, ) _relations = ( ("dependencies", ToMany(ToMany, "Products.ZenModel.ManagedEntity", "dependents")), ("dependents", ToMany(ToMany, "Products.ZenModel.ManagedEntity", "dependencies")), ("componentGroups", ToMany(ToMany, "Products.ZenModel.ComponentGroup", "components")), ("maintenanceWindows", ToManyCont(ToOne, "Products.ZenModel.MaintenanceWindow", "productionState")), ) security = ClassSecurityInfo() def device(self): """Overridden in lower classes if a device relationship exists. """ return None def getProductionState(self): return self.privateattr_productionState def _setProductionState(self, state): self.privateattr_productionState = state def getPreMWProductionState(self): return getattr(self, '_preMWProductionState', None) def setPreMWProductionState(self, state): self._preMWProductionState = state def resetProductionState(self): # The Device class should override this and set a default value try: del self.privateattr_productionState except AttributeError: pass try: del self._preMWProductionState except AttributeError: pass # In order to maintain backward-compatibility, we need to preserve productionState as a property. productionState = property(getProductionState, _setProductionState, resetProductionState) preMWProductionState = property(getPreMWProductionState, setPreMWProductionState) def getProductionStateString(self): """ Return the prodstate as a string. @rtype: string """ return str(self.convertProdState(self.getProductionState())) security.declareProtected(ZEN_CHANGE_DEVICE_PRODSTATE, 'setProdState') def setProdState(self, state, maintWindowChange=False, REQUEST=None): """ Set the device's production state. @parameter state: new production state @type state: int @parameter maintWindowChange: are we resetting state from inside a MW? @type maintWindowChange: boolean @permission: ZEN_CHANGE_DEVICE """ self._setProductionState(int(state)) indexEvent = IndexingEvent( self.primaryAq(), ('productionState', ), True, ) indexEvent.triggered_by_maint_window = maintWindowChange notify(indexEvent) if not maintWindowChange: # Saves our production state for use at the end of the # maintenance window. self.setPreMWProductionState(self.getProductionState()) if REQUEST: IMessageSender(self).sendToBrowser( "Production State Set", "%s's production state was set to %s." % (self.id, self.getProductionStateString())) return self.callZenScreen(REQUEST) def getComponentGroupNames(self): # lazily create the relationship so we don't have to do a migrate script if not hasattr(self, "componentGroups"): return [] return [group.getOrganizerName() for group in self.componentGroups()] def getComponentGroups(self): # lazily create the relationship so we don't have to do a migrate script if not hasattr(self, "componentGroups"): return [] return self.componentGroups() def setComponentGroups(self, groupPaths): relPaths = groupPaths if not hasattr(self, "componentGroups"): self.buildRelations() objGetter = self.dmd.ComponentGroups.createOrganizer relName = "componentGroups" # set the relations between the component (self) and the groups if not isinstance(relPaths, (list, tuple)): relPaths = [ relPaths, ] relPaths = filter(lambda x: x.strip(), relPaths) rel = getattr(self, relName, None) curRelIds = {} # set a relationship for every group for value in rel.objectValuesAll(): curRelIds[value.getOrganizerName()] = value for path in relPaths: if path not in curRelIds: robj = objGetter(path) self.addRelation(relName, robj) else: del curRelIds[path] # remove any that were left over for obj in curRelIds.values(): self.removeRelation(relName, obj) # reindex self.index_object() notify(IndexingEvent(self, 'path', False))
class PerformanceConf(Monitor, StatusColor): """ Configuration for Performance servers """ portal_type = meta_type = 'PerformanceConf' monitorRootName = 'Performance' security = ClassSecurityInfo() security.setDefaultAccess('allow') eventlogCycleInterval = 60 perfsnmpCycleInterval = 300 processCycleInterval = 180 statusCycleInterval = 60 winCycleInterval = 60 wmibatchSize = 10 wmiqueryTimeout = 100 configCycleInterval = 6 * 60 zenProcessParallelJobs = 10 pingTimeOut = 1.5 pingTries = 2 pingChunk = 75 pingCycleInterval = 60 maxPingFailures = 1440 modelerCycleInterval = 720 discoveryNetworks = () _properties = ( { 'id': 'eventlogCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'processCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'statusCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'winCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'wmibatchSize', 'type': 'int', 'mode': 'w', 'description': "Number of data objects to retrieve in a single WMI query" }, { 'id': 'wmiqueryTimeout', 'type': 'int', 'mode': 'w', 'description': "Number of milliseconds to wait for WMI query to respond" }, { 'id': 'configCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'zenProcessParallelJobs', 'type': 'int', 'mode': 'w' }, { 'id': 'pingTimeOut', 'type': 'float', 'mode': 'w' }, { 'id': 'pingTries', 'type': 'int', 'mode': 'w' }, { 'id': 'pingChunk', 'type': 'int', 'mode': 'w' }, { 'id': 'pingCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'maxPingFailures', 'type': 'int', 'mode': 'w' }, { 'id': 'modelerCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'discoveryNetworks', 'type': 'lines', 'mode': 'w' }, ) _relations = Monitor._relations + ( ("devices", ToMany(ToOne, "Products.ZenModel.Device", "perfServer")), ) # Screen action bindings (and tab definitions) factory_type_information = ({ 'immediate_view': 'viewPerformanceConfOverview', 'actions': ( { 'id': 'overview', 'name': 'Overview', 'action': 'viewPerformanceConfOverview', 'permissions': (permissions.view, ) }, { 'id': 'edit', 'name': 'Edit', 'action': 'editPerformanceConf', 'permissions': ("Manage DMD", ) }, { 'id': 'performance', 'name': 'Performance', 'action': 'viewDaemonPerformance', 'permissions': (permissions.view, ) }, ) }, ) def findDevice(self, deviceName): """ Return the object given the name @param deviceName: Name of a device @type deviceName: string @return: device corresponding to the name, or None @rtype: device object """ brains = self.dmd.Devices._findDevice(deviceName) if brains: return brains[0].getObject() def findDeviceByIdExact(self, deviceName): """ Look up device in catalog and return it. devicename must match device id exactly @param deviceName: Name of a device @type deviceName: string @return: device corresponding to the name, or None @rtype: device object """ dev = self.dmd.Devices.findDeviceByIdExact(deviceName) if dev: return dev def getNetworkRoot(self, version=None): """ Get the root of the Network object in the DMD @return: base DMD Network object @rtype: Network object """ return self.dmd.Networks.getNetworkRoot(version) security.declareProtected('View', 'performanceDeviceList') def performanceDeviceList(self, force=True): """ Return a list of URLs that point to our managed devices @param force: unused @type force: boolean @return: list of device objects @rtype: list """ unused(force) devlist = [] for dev in self.devices(): dev = dev.primaryAq() if not dev.pastSnmpMaxFailures() and dev.monitorDevice(): devlist.append(dev.getPrimaryUrlPath()) return devlist security.declareProtected('View', 'performanceDataSources') def performanceDataSources(self): """ Return a string that has all the definitions for the performance DS's. @return: list of Data Sources @rtype: string """ dses = [] oidtmpl = 'OID %s %s' dstmpl = """datasource %s rrd-ds-type = %s ds-source = snmp://%%snmp%%/%s%s """ rrdconfig = self.getDmdRoot('Devices').rrdconfig for ds in rrdconfig.objectValues(spec='RRDDataSource'): if ds.isrow: inst = '.%inst%' else: inst = '' dses.append(oidtmpl % (ds.getName(), ds.oid)) dses.append(dstmpl % (ds.getName(), ds.rrdtype, ds.getName(), inst)) return '\n'.join(dses) def setPerformanceMonitor(self, performanceMonitor=None, deviceNames=None, REQUEST=None): """ Provide a method to set performance monitor from any organizer @param performanceMonitor: DMD object that collects from a device @type performanceMonitor: DMD object @param deviceNames: list of device names @type deviceNames: list @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object """ if not performanceMonitor: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No monitor was selected.', priority=messaging.WARNING) return self.callZenScreen(REQUEST) if deviceNames is None: if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', 'No devices were selected.', priority=messaging.WARNING) return self.callZenScreen(REQUEST) for devName in deviceNames: dev = self.devices._getOb(devName) dev = dev.primaryAq() dev.setPerformanceMonitor(performanceMonitor) if REQUEST: audit('UI.Device.ChangeCollector', dev, collector=performanceMonitor) if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Monitor Set', 'Performance monitor was set to %s.' % performanceMonitor) if "oneKeyValueSoInstanceIsntEmptyAndEvalToFalse" in REQUEST: return REQUEST['message'] else: return self.callZenScreen(REQUEST) security.declareProtected('View', 'getPingDevices') def getPingDevices(self): """ Return devices associated with this monitor configuration. @return: list of devices for this monitor @rtype: list """ devices = [] for dev in self.devices.objectValuesAll(): dev = dev.primaryAq() if dev.monitorDevice() and not dev.zPingMonitorIgnore: devices.append(dev) return devices def addCreateDeviceJob( self, deviceName, devicePath, title=None, discoverProto="none", manageIp="", performanceMonitor=None, rackSlot=0, productionState=1000, comments="", hwManufacturer="", hwProductName="", osManufacturer="", osProductName="", priority=3, locationPath="", systemPaths=[], groupPaths=[], tag="", serialNumber="", zProperties={}, cProperties={}, ): """ Creating a device has two steps: creating a 'stub' device in the database, then (if requested) running zendisc to model the device. The modeling step can be skipped if the discoverProto argument is set to the string "none". @returns A list of JobRecord objects. """ # Determine the name of the monitor to use. monitor = performanceMonitor or self.id # Check to see if we got passed in an IPv6 address try: IPAddress(deviceName) if not title: title = deviceName deviceName = ipwrap(deviceName) except ValueError: pass # Creating a device is, at most, a two-step process. First a # device 'stub' is created in the database then, if the # discoverProto argument is not 'none', then zendisc is run to # discover and model the device. The process is implemented using # two jobs. subjobs = [ CreateDeviceJob.makeSubJob(args=(deviceName, ), kwargs=dict( devicePath=devicePath, title=title, discoverProto=discoverProto, manageIp=manageIp, performanceMonitor=monitor, rackSlot=rackSlot, productionState=productionState, comments=comments, hwManufacturer=hwManufacturer, hwProductName=hwProductName, osManufacturer=osManufacturer, osProductName=osProductName, priority=priority, tag=tag, serialNumber=serialNumber, locationPath=locationPath, systemPaths=systemPaths, groupPaths=groupPaths, zProperties=zProperties, cProperties=cProperties, )) ] if discoverProto != 'none': zendiscCmd = self._getZenDiscCommand(deviceName, devicePath, monitor, productionState) subjobs.append( SubprocessJob.makeSubJob( args=(zendiscCmd, ), description="Discover and model device %s as %s" % (deviceName, devicePath))) # Set the 'immutable' flag to indicate that the result of the prior # job is not passed as arguments into the next job (basically, args # to the jobs are immutable). return self.dmd.JobManager.addJobChain(*subjobs, immutable=True) @deprecated def addDeviceCreationJob(self, deviceName, devicePath, title=None, discoverProto="none", manageIp="", performanceMonitor=None, rackSlot=0, productionState=1000, comments="", hwManufacturer="", hwProductName="", osManufacturer="", osProductName="", priority=3, locationPath="", systemPaths=[], groupPaths=[], tag="", serialNumber="", zProperties={}): """ For backward compatibility. Please use the addCreateDeviceJob method instead of the addDeviceCreationJob method. """ result = self.addCreateDeviceJob(deviceName, devicePath, title=title, discoverProto=discoverProto, manageIp=manageIp, performanceMonitor=performanceMonitor, rackSlot=rackSlot, productionState=productionState, comments=comments, hwManufacturer=hwManufacturer, hwProductName=hwProductName, osManufacturer=osManufacturer, osProductName=osProductName, priority=priority, locationPath=locationPath, systemPaths=systemPaths, groupPaths=groupPaths, tag=tag, serialNumber=serialNumber, zProperties=zProperties) return result[-1] def _executeZenDiscCommand(self, deviceName, devicePath="/Discovered", performanceMonitor="localhost", productionState=1000, background=False, REQUEST=None): """ Execute zendisc on the new device and return result @param deviceName: Name of a device @type deviceName: string @param devicePath: DMD path to create the new device in @type devicePath: string @param performanceMonitor: DMD object that collects from a device @type performanceMonitor: DMD object @param background: should command be scheduled job? @type background: boolean @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object @return: @rtype: """ args = [deviceName, devicePath, performanceMonitor, productionState] if background: zendiscCmd = self._getZenDiscCommand(*args) result = self.dmd.JobManager.addJob( SubprocessJob, args=(zendiscCmd, ), description="Discover and model device %s as %s" % (args[0], args[1])) else: args.append(REQUEST) zendiscCmd = self._getZenDiscCommand(*args) result = self._executeCommand(zendiscCmd, REQUEST) return result def _getZenDiscCommand(self, deviceName, devicePath, performanceMonitor, productionState, REQUEST=None, max_seconds=None): zm = binPath('zendisc') zendiscCmd = [zm] deviceName = self._escapeParentheses(deviceName) zendiscOptions = [ 'run', '--now', '-d', deviceName, '--monitor', performanceMonitor, '--deviceclass', devicePath, '--prod_state', str(productionState) ] if REQUEST: zendiscOptions.append("--weblog") zendiscCmd.extend(zendiscOptions) log.info('local zendiscCmd is "%s"' % ' '.join(zendiscCmd)) return zendiscCmd def getCollectorCommand(self, command): return [binPath(command)] def executeCollectorCommand(self, command, args, REQUEST=None): """ Executes the collector based daemon command. @param command: the collector daemon to run, should not include path @type command: string @param args: list of arguments for the command @type args: list of strings @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object @return: result of the command @rtype: string """ cmd = binPath(command) daemonCmd = [cmd] daemonCmd.extend(args) result = self._executeCommand(daemonCmd, REQUEST) return result def collectDevice(self, device=None, setlog=True, REQUEST=None, generateEvents=False, background=False, write=None, collectPlugins='', debug=False): """ Collect the configuration of this device AKA Model Device @permission: ZEN_MANAGE_DEVICE @param device: Name of a device or entry in DMD @type device: string @param setlog: If true, set up the output log of this process @type setlog: boolean @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object @param generateEvents: unused @type generateEvents: string @param collectPlugins: (optional) Modeler plugins to use. Takes a regular expression (default: '') @type collectPlugins: string """ xmlrpc = isXmlRpc(REQUEST) result = self._executeZenModelerCommand(device.id, self.id, background, REQUEST, write, collectPlugins=collectPlugins, debug=debug) if result and xmlrpc: return result log.info('configuration collected') if xmlrpc: return 0 def _executeZenModelerCommand(self, deviceName, performanceMonitor="localhost", background=False, REQUEST=None, write=None, collectPlugins='', debug=False): """ Execute zenmodeler and return result @param deviceName: The name of the device @type deviceName: string @param performanceMonitor: Name of the collector @type performanceMonitor: string @param REQUEST: Zope REQUEST object @type REQUEST: Zope REQUEST object @param collectPlugins: (optional) Modeler plugins to use. Takes a regular expression (default: '') @type collectPlugins: string @return: results of command @rtype: string """ args = [deviceName, performanceMonitor, collectPlugins] if background: zenmodelerCmd = self._getZenModelerCommand(*args) log.info('queued job: %s', " ".join(zenmodelerCmd)) result = self.dmd.JobManager.addJob( SubprocessJob, description="Run zenmodeler %s" % ' '.join(zenmodelerCmd), args=(zenmodelerCmd, )) else: args.append(REQUEST) zenmodelerCmd = self._getZenModelerCommand(*args) if debug: zenmodelerCmd.append('-v10') result = self._executeCommand(zenmodelerCmd, REQUEST, write) return result def _getZenModelerCommand(self, deviceName, performanceMonitor, collectPlugins='', REQUEST=None): zm = binPath('zenmodeler') cmd = [zm] deviceName = self._escapeParentheses(deviceName) options = [ 'run', '--now', '-d', deviceName, '--monitor', performanceMonitor, '--collect={}'.format(collectPlugins) ] cmd.extend(options) log.info('local zenmodelerCmd is "%s"' % ' '.join(cmd)) return cmd def _executeCommand(self, remoteCommand, REQUEST=None, write=None): result = executeCommand(remoteCommand, REQUEST, write) return result def _escapeParentheses(self, string): """ Escape unascaped parentheses. """ compiled = re.compile(r'(?<!\\)(?P<char>[()])') return compiled.sub(r'\\\g<char>', string)
class IpAddress(ManagedEntity, IpAddressIndexable): """IpAddress object""" event_key = portal_type = meta_type = 'IpAddress' default_catalog = 'ipSearch' version = 4 _properties = ( {'id':'netmask', 'type':'string', 'mode':'w', 'setter':'setNetmask'}, {'id':'ptrName', 'type':'string', 'mode':'w'}, {'id':'version', 'type':'int', 'mode':'w'}, ) _relations = ManagedEntity._relations + ( ("network", ToOne(ToManyCont,"Products.ZenModel.IpNetwork","ipaddresses")), ("interface", ToOne(ToMany,"Products.ZenModel.IpInterface","ipaddresses")), ("manageDevice", ToOne(ToOne,"Products.ZenModel.Device","ipaddress")), ("clientroutes", ToMany(ToOne,"Products.ZenModel.IpRouteEntry","nexthop")), ) factory_type_information = ( { 'id' : 'IpAddress', 'meta_type' : 'IpAddress', 'description' : """Ip Address Class""", 'icon' : 'IpAddress_icon.gif', 'product' : 'ZenModel', 'factory' : 'manage_addIpAddress', 'immediate_view' : 'viewIpAddressOverview', 'actions' : ( { 'id' : 'overview' , 'name' : 'Overview' , 'action' : 'viewIpAddressOverview' , 'permissions' : ( "View", ) }, ) }, ) security = ClassSecurityInfo() def __init__(self, id, netmask=24): checkip(id) ManagedEntity.__init__(self, ipwrap(id)) ipobj = IPAddress(ipunwrap_strip(id)) if ipobj.version == 6: # No user-definable subnet masks for IPv6 netmask = 64 self._netmask = maskToBits(netmask) self.ptrName = None self.title = ipunwrap(id) self.version = ipobj.version def setPtrName(self): try: data = socket.gethostbyaddr(ipunwrap(self.id)) if data: self.ptrName = data[0] except socket.error as e: self.ptrName = "" log.warn("%s: %s", self.title, e) security.declareProtected('View', 'primarySortKey') def primarySortKey(self): """ Make sure that networks sort correctly """ return ipToDecimal(self.id) def setNetmask(self, value): self._netmask = maskToBits(value) def _setPropValue(self, id, value): """ Override from PerpertyManager to handle checks and IP creation """ self._wrapperCheck(value) if id == 'netmask': self.setNetmask(value) else: setattr(self,id,value) def __getattr__(self, name): if name == 'netmask': return self._netmask else: raise AttributeError( name ) security.declareProtected('Change Device', 'setIpAddress') def setIpAddress(self, ip): """ Set the IP address. Use the format 1.1.1.1/24 to also set the netmask """ iparray = ip.split("/") if len(iparray) > 1: ip = iparray[0] self._netmask = maskToBits(iparray[1]) checkip(ip) aqself = self.primaryAq() #set aq path network = aqself.aq_parent netip = netFromIpAndNet(ip, network.netmask) if netip == network.id: network._renameObject(aqself.id, ipwrap(ip)) else: raise WrongSubnetError( "IP %s is in a different subnet than %s" % (ipunwrap(ip), ipunwrap(self.id)) ) security.declareProtected('View', 'getIp') def getIp(self): """ Return only the IP address """ return ipunwrap(self.id) security.declareProtected('View', 'getIpAddress') def getIpAddress(self): """ Return the IP with its netmask in the form 1.1.1.1/24 """ return ipunwrap(self.id) + "/" + str(self._netmask) def __str__(self): return self.getIpAddress() security.declareProtected('View', 'getInterfaceName') def getInterfaceName(self): if self.interface(): return self.interface().name() return "No Interface" security.declareProtected('View', 'getDeviceName') def getDeviceName(self): if self.interface(): return self.device().titleOrId() return "No Device" security.declareProtected('View', 'getNetworkName') def getNetworkName(self): if self.network(): return self.network().getNetworkName() return "No Network" def getInterfaceDescription(self): """ Used for indexing """ if self.interface(): return self.interface().description def getInterfaceMacAddress(self): """ Used for indexing """ if self.interface(): return self.interface().macaddress security.declareProtected('View', 'getNetworkUrl') def getNetworkUrl(self): if self.network(): return self.network().absolute_url_path() return "" security.declareProtected('View', 'getDeviceUrl') def getDeviceUrl(self): """ Get the primary URL path of the device to which this IP is associated. If no device return the URL to the IP itself. """ d = self.device() if d: return d.getPrimaryUrlPath() else: return self.getPrimaryUrlPath() def device(self): """ Return the device for this IP """ iface = self.interface() if iface: return iface.device() return None def index_object(self, idxs=None): """ DEPRECATED """ pass def unindex_object(self): """ DEPRECATED """ pass def deviceId(self): """ The device id, for indexing purposes. """ d = self.device() if d: return d.id else: return None def interfaceId(self): """ The interface id, for indexing purposes. """ i = self.interface() if i: return i.id else: return None def ipAddressId(self): """ The ipAddress id, for indexing purposes. """ return self.getPrimaryId() def networkId(self): """ The network id, for indexing purposes. """ n = self.network() if n: return n.getPrimaryId() else: return None def ipAddressAsInt(self): ip = self.getIpAddress() if ip: ip = ip.partition('/')[0] return str(numbip(ip)) #------------------------------------------ #-- ITreeSpanningComponent methods -- def get_indexable_peers(self): """ """ peers = [] if self.device(): peers.append(self.device().primaryAq()) if self.interface(): peers.append(self.interface().primaryAq()) return peers
class ManagedEntity(ZenModelRM, DeviceResultInt, EventView, RRDView, MaintenanceWindowable): """ ManagedEntity is an entity in the system that is managed by it. Its basic property is that it can be classified by the ITClass Tree. Also has EventView and RRDView available. """ # list of performance multigraphs (see PerformanceView.py) # FIXME this needs to go to some new setup and doesn't work now #_mgraphs = [] # primary snmpindex for this managed entity snmpindex = 0 snmpindex_dct = {} monitor = True _properties = ( { 'id': 'snmpindex', 'type': 'string', 'mode': 'w' }, { 'id': 'monitor', 'type': 'boolean', 'mode': 'w' }, { 'id': 'productionState', 'type': 'keyedselection', 'mode': 'w', 'select_variable': 'getProdStateConversions', 'setter': 'setProdState' }, { 'id': 'preMWProductionState', 'type': 'keyedselection', 'mode': 'w', 'select_variable': 'getProdStateConversions', 'setter': 'setProdState' }, ) _relations = ( ("dependencies", ToMany(ToMany, "Products.ZenModel.ManagedEntity", "dependents")), ("dependents", ToMany(ToMany, "Products.ZenModel.ManagedEntity", "dependencies")), ("maintenanceWindows", ToManyCont(ToOne, "Products.ZenModel.MaintenanceWindow", "productionState")), ) security = ClassSecurityInfo() def device(self): """Overridden in lower classes if a device relationship exists. """ return None def getProductionStateString(self): """ Return the prodstate as a string. @rtype: string """ return self.convertProdState(self.productionState) security.declareProtected(ZEN_CHANGE_DEVICE_PRODSTATE, 'setProdState') def setProdState(self, state, maintWindowChange=False, REQUEST=None): """ Set the device's production state. @parameter state: new production state @type state: int @parameter maintWindowChange: are we resetting state from inside a MW? @type maintWindowChange: boolean @permission: ZEN_CHANGE_DEVICE """ self.productionState = int(state) self.primaryAq().index_object() notify(IndexingEvent(self.primaryAq(), ('productionState', ), True)) if not maintWindowChange: # Saves our production state for use at the end of the # maintenance window. self.preMWProductionState = self.productionState if REQUEST: IMessageSender(self).sendToBrowser( "Production State Set", "%s's production state was set to %s." % (self.id, self.getProductionStateString())) return self.callZenScreen(REQUEST)
class EC2Instance(AWSComponent): ''' Model class for EC2Instance. ''' meta_type = portal_type = 'EC2Instance' instance_id = None region = None instance_type = None image_id = None state = None platform = None private_ip_address = None public_dns_name = None launch_time = None detailed_monitoring = None # Used to restore user-defined production state when a stopped # instance is resumed. _running_prodstate = 1000 _properties = AWSComponent._properties + ( {'id': 'instance_id', 'type': 'string'}, {'id': 'public_dns_name', 'type': 'string'}, {'id': 'private_ip_address', 'type': 'string'}, {'id': 'image_id', 'type': 'string'}, {'id': 'instance_type', 'type': 'string'}, {'id': 'launch_time', 'type': 'string'}, {'id': 'state', 'type': 'string'}, {'id': 'region', 'type': 'string'}, {'id': 'platform', 'type': 'string'}, {'id': 'detailed_monitoring', 'type': 'boolean'}, ) _relations = AWSComponent._relations + ( ('region', ToOne( ToManyCont, MODULE_NAME['EC2Region'], 'instances')), ('zone', ToOne( ToMany, MODULE_NAME['EC2Zone'], 'instances')), ('volumes', ToMany( ToOne, MODULE_NAME['EC2Volume'], 'instance')), ('vpc_subnet', ToOne( ToMany, MODULE_NAME['EC2VPCSubnet'], 'instances')), ) def getIconPath(self): ''' Return the path to an icon for this component. ''' if self.detailed_monitoring: img_name = 'EC2Instance-cw' else: img_name = 'EC2Instance' return '/++resource++aws/img/%s.png' % img_name def monitored(self): ''' Return True if this instance should be monitored. False otherwise. ''' if self.state and self.state.lower() == 'running': return True return False def getRRDTemplates(self): template_names = [] if self.detailed_monitoring: template_names.append('EC2Instance-Detailed') else: template_names.append('EC2Instance') template_names.append('EC2Instance-Custom') templates = [] for template_name in template_names: template = self.getRRDTemplateByName(template_name) if template: templates.append(template) return templates def getDimension(self): return 'InstanceId=%s' % self.id def getRegionId(self): return self.region().id def getZoneId(self): zone = self.zone() if zone: return zone.id def setZoneId(self, id_): updateToOne( self.zone, self.region().zones, CLASS_NAME['EC2Zone'], id_) def getVolumeIds(self): return sorted(self.volumes.objectIds()) def setVolumeIds(self, ids): updateToMany( self.volumes, self.region().volumes, CLASS_NAME['EC2Volume'], ids) def getVPCSubnetId(self): vpc_subnet = self.vpc_subnet() if vpc_subnet: return vpc_subnet.id def setVPCSubnetId(self, id_): updateToOne( self.vpc_subnet, self.region().vpc_subnets, CLASS_NAME['EC2VPCSubnet'], id_) def vpc(self): ''' Return the VPC for this instance or None. ''' subnet = self.vpc_subnet() if subnet: return subnet.vpc() def guest_manage_ip(self): ''' Return the best manageIp for this instance's guest device or None if no good option is found. ''' if self.vpc(): return self.private_ip_address if self.public_dns_name: try: import socket return socket.gethostbyname(self.public_dns_name) except socket.gaierror: pass def guest_device(self): ''' Return guest device object or None if not found. ''' # OPTIMIZE: On systems with a large number of devices it might # be more optimal to first try searching only within # instance.guest_deviceclass() device = self.findDeviceByIdExact(self.id) if device: return device if self.title and self.title != self.id: device = self.findDeviceByIdExact(self.title) if device: return device ip_address = self.guest_manage_ip() if ip_address: device = self.findDeviceByIdOrIp(ip_address) if device: return device def guest_deviceclass(self): ''' Return destination device class for this instance's guest device or None if not set. ''' path = None if self.platform and 'windows' in self.platform.lower(): path = self.device().windowsDeviceClass else: path = self.device().linuxDeviceClass if path: return self.getDmdRoot('Devices').createOrganizer(path) def guest_collector(self): ''' Return the best collector for this instance's guest device. ''' vpc = self.vpc() if vpc and vpc.collector: collector = self.getDmdRoot('Monitors').Performance._getOb( vpc.collector, None) if collector: return collector return self.getPerformanceServer() def create_guest(self): ''' Create guest device for this instance if it doesn't already exist. ''' deviceclass = self.guest_deviceclass() if not deviceclass: return manage_ip = self.guest_manage_ip() if not manage_ip: return collector = self.guest_collector() if not collector: return if self.guest_device(): return LOG.info( 'instance %s running. Discovering guest device', self.titleOrId()) device = deviceclass.createInstance(self.id) device.title = self.title device.setManageIp(manage_ip) device.setPerformanceMonitor(collector.id) device.setProdState(self._running_prodstate) device.index_object() notify(IndexingEvent(device)) # Schedule a modeling job for the new device. device.collectDevice(setlog=False, background=True) def discover_guest(self): ''' Attempt to discover and link guest device. ''' if not self.state: return deviceclass = self.guest_deviceclass() if not deviceclass: return if self.state.lower() == 'running': guest_device = self.guest_device() if guest_device: if guest_device.productionState != self._running_prodstate: LOG.info( 'instance %s running. Changing guest device ' 'to production', self.titleOrId()) guest_device.setProdState(self._running_prodstate) else: self.create_guest() elif self.state.lower() == 'stopped': guest_device = self.guest_device() if guest_device: if guest_device.productionState != -1: LOG.info( 'instance %s stopped. Decommissioning guest device', self.titleOrId()) guest_device.setProdState(-1)
class Host(BaseComponent): meta_type = portal_type = "CloudStackHost" host_type = None host_state = None host_events = None host_version = None hypervisor = None capabilities = None created = None host_tags = None ip_address = None local_storage_active = None management_server_id = None _properties = BaseComponent._properties + ( { 'id': 'host_type', 'type': 'string', 'mode': '' }, { 'id': 'host_state', 'type': 'string', 'mode': '' }, { 'id': 'host_events', 'type': 'string', 'mode': '' }, { 'id': 'host_version', 'type': 'string', 'mode': '' }, { 'id': 'hypervisor', 'type': 'string', 'mode': '' }, { 'id': 'capabilities', 'type': 'string', 'mode': '' }, { 'id': 'created', 'type': 'string', 'mode': '' }, { 'id': 'host_tags', 'type': 'string', 'mode': '' }, { 'id': 'ip_address', 'type': 'string', 'mode': '' }, { 'id': 'local_storage_active', 'type': 'boolean', 'mode': '' }, { 'id': 'management_server_id', 'type': 'int', 'mode': '' }, ) _relations = BaseComponent._relations + ( ('cluster', ToOne(ToManyCont, 'ZenPacks.zenoss.CloudStack.Cluster.Cluster', 'hosts')), ('systemvms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.SystemVM.SystemVM', 'host')), ('routervms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.RouterVM.RouterVM', 'host')), ('vms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.VirtualMachine.VirtualMachine', 'host')), ) def device(self): return self.cluster().device() def getManagedDevice(self): device = self.findDevice(self.ip_address) if device: return device ip = self.getDmdRoot("Networks").findIp(self.ip_address) if ip: return ip.device()
class PerformanceConf(Monitor, StatusColor): """ Configuration for Performance servers """ portal_type = meta_type = 'PerformanceConf' monitorRootName = 'Performance' security = ClassSecurityInfo() security.setDefaultAccess('allow') eventlogCycleInterval = 60 perfsnmpCycleInterval = 300 processCycleInterval = 180 statusCycleInterval = 60 winCycleInterval = 60 wmibatchSize = 10 wmiqueryTimeout = 100 configCycleInterval = 6 * 60 zenProcessParallelJobs = 10 pingTimeOut = 1.5 pingTries = 2 pingChunk = 75 pingCycleInterval = 60 maxPingFailures = 1440 modelerCycleInterval = 720 renderurl = '/zport/RenderServer' renderuser = '' renderpass = '' discoveryNetworks = () # make the default rrdfile size smaller # we need the space to live within the disk cache defaultRRDCreateCommand = ( 'RRA:AVERAGE:0.5:1:600', # every 5 mins for 2 days 'RRA:AVERAGE:0.5:6:600', # every 30 mins for 12 days 'RRA:AVERAGE:0.5:24:600', # every 2 hours for 50 days 'RRA:AVERAGE:0.5:288:600', # every day for 600 days 'RRA:MAX:0.5:6:600', 'RRA:MAX:0.5:24:600', 'RRA:MAX:0.5:288:600', ) _properties = ( { 'id': 'eventlogCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'processCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'statusCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'winCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'wmibatchSize', 'type': 'int', 'mode': 'w', 'description': "Number of data objects to retrieve in a single WMI query", }, { 'id': 'wmiqueryTimeout', 'type': 'int', 'mode': 'w', 'description': "Number of milliseconds to wait for WMI query to respond", }, { 'id': 'configCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'renderurl', 'type': 'string', 'mode': 'w' }, { 'id': 'renderuser', 'type': 'string', 'mode': 'w' }, { 'id': 'renderpass', 'type': 'string', 'mode': 'w' }, { 'id': 'defaultRRDCreateCommand', 'type': 'lines', 'mode': 'w' }, { 'id': 'zenProcessParallelJobs', 'type': 'int', 'mode': 'w' }, { 'id': 'pingTimeOut', 'type': 'float', 'mode': 'w' }, { 'id': 'pingTries', 'type': 'int', 'mode': 'w' }, { 'id': 'pingChunk', 'type': 'int', 'mode': 'w' }, { 'id': 'pingCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'maxPingFailures', 'type': 'int', 'mode': 'w' }, { 'id': 'modelerCycleInterval', 'type': 'int', 'mode': 'w' }, { 'id': 'discoveryNetworks', 'type': 'lines', 'mode': 'w' }, ) _relations = Monitor._relations + ( ("devices", ToMany(ToOne, "Products.ZenModel.Device", "perfServer")), ) # Screen action bindings (and tab definitions) factory_type_information = ({ 'immediate_view': 'viewPerformanceConfOverview', 'actions': ( { 'id': 'overview', 'name': 'Overview', 'action': 'viewPerformanceConfOverview', 'permissions': (permissions.view, ) }, { 'id': 'edit', 'name': 'Edit', 'action': 'editPerformanceConf', 'permissions': ("Manage DMD", ) }, { 'id': 'performance', 'name': 'Performance', 'action': 'viewDaemonPerformance', 'permissions': (permissions.view, ) }, ) }, ) security.declareProtected('View', 'getDefaultRRDCreateCommand') def getDefaultRRDCreateCommand(self): """ Get the default RRD Create Command, as a string. For example: '''RRA:AVERAGE:0.5:1:600 RRA:AVERAGE:0.5:6:600 RRA:AVERAGE:0.5:24:600 RRA:AVERAGE:0.5:288:600 RRA:MAX:0.5:288:600''' @return: RRD create command @rtype: string """ return '\n'.join(self.defaultRRDCreateCommand) def findDevice(self, deviceName): """ Return the object given the name @param deviceName: Name of a device @type deviceName: string @return: device corresponding to the name, or None @rtype: device object """ brains = self.dmd.Devices._findDevice(deviceName) if brains: return brains[0].getObject() def getNetworkRoot(self, version=None): """ Get the root of the Network object in the DMD @return: base DMD Network object @rtype: Network object """ return self.dmd.Networks.getNetworkRoot(version) def buildGraphUrlFromCommands(self, gopts, drange): """ Return an URL for the given graph options and date range @param gopts: graph options @type gopts: string @param drange: time range to use @type drange: string @return: URL to a graphic @rtype: string """ newOpts = [] width = 0 for o in gopts: if o.startswith('--width'): width = o.split('=')[1].strip() continue newOpts.append(o) encodedOpts = urlsafe_b64encode(zlib.compress('|'.join(newOpts), 9)) params = { 'gopts': encodedOpts, 'drange': drange, 'width': width, } url = self._getSanitizedRenderURL() if RenderURLUtil(self.renderurl).proxiedByZenoss(): params['remoteHost'] = self.getRemoteRenderUrl() url = '/zport/RenderServer' url = '%s/render?%s' % ( url, urlencode(params), ) return url def _getSanitizedRenderURL(self): """ remove any keywords/directives from renderurl. example is "proxy://host:8091" is changed to "http://host:8091" """ return RenderURLUtil(self.renderurl).getSanitizedRenderURL() def performanceGraphUrl(self, context, targetpath, targettype, view, drange): """ Set the full path of the target and send to view @param context: Where you are in the Zope acquisition path @type context: Zope context object @param targetpath: device path of performance metric @type targetpath: string @param targettype: unused @type targettype: string @param view: view object @type view: Zope object @param drange: date range @type drange: string @return: URL to graph @rtype: string """ unused(targettype) targetpath = performancePath(targetpath) gopts = view.getGraphCmds(context, targetpath) return self.buildGraphUrlFromCommands(gopts, drange) def getRemoteRenderUrl(self): """ return the full render url with http protocol prepended if the renderserver is remote. Return empty string otherwise """ return RenderURLUtil(self.renderurl).getRemoteRenderUrl() def _get_render_server(self, allow_none=False, timeout=None): if self.getRemoteRenderUrl(): renderurl = self.getRemoteRenderUrl() # Going through the hub or directly to zenrender log.info("Remote renderserver at %s", renderurl) url = basicAuthUrl(str(self.renderuser), str(self.renderpass), renderurl) server = xmlrpclib.Server(url, allow_none=allow_none) if timeout is not None: addXmlServerTimeout(server, timeout) else: if not self.renderurl: raise KeyError("No render URL is defined") server = self.getObjByPath(self.renderurl) return server def performanceCustomSummary(self, gopts, timeout=SUMMARY_COLLECTOR_REQUEST_TIMEOUT): """ Fill out full path for custom gopts and call to server @param gopts: graph options @type gopts: string @param timeout: the connection timeout in seconds. By default the value is 5s or the value for the global property 'collectorRequestTimeout' None translates to the global default socket timeout. 0 would translate to 'never timeout'. @type timeout: float @return: URL @rtype: string """ gopts = self._fullPerformancePath(gopts) server = self._get_render_server(timeout=timeout) try: value = server.summary(gopts) return value except IOError, e: log.error( "Error collecting performance summary from collector %s: %s", self.id, e) log.debug("Error collecting with params %s", gopts)
class EC2VPCSubnet(AWSComponent): ''' Model class for EC2VPCSubnet. ''' meta_type = portal_type = 'EC2VPCSubnet' available_ip_address_count = None cidr_block = None defaultForAz = None mapPublicIpOnLaunch = None state = None _properties = AWSComponent._properties + ( { 'id': 'available_ip_address_count', 'type': 'int' }, { 'id': 'cidr_block', 'type': 'string' }, { 'id': 'defaultForAz', 'type': 'boolean' }, { 'id': 'mapPublicIpOnLaunch', 'type': 'boolean' }, { 'id': 'state', 'type': 'string' }, ) _relations = AWSComponent._relations + ( ('region', ToOne(ToManyCont, MODULE_NAME['EC2Region'], 'vpc_subnets')), ('vpc', ToOne(ToMany, MODULE_NAME['EC2VPC'], 'vpc_subnets')), ('zone', ToOne(ToMany, MODULE_NAME['EC2Zone'], 'vpc_subnets')), ('instances', ToMany(ToOne, MODULE_NAME['EC2Instance'], 'vpc_subnet')), ) def getRegionId(self): return self.region().id def getVPCId(self): vpc = self.vpc() if vpc: return vpc.id def setVPCId(self, id_): updateToOne(self.vpc, self.region().vpcs, CLASS_NAME['EC2VPC'], id_) def getZoneId(self): zone = self.zone() if zone: return zone.id def setZoneId(self, id_): updateToOne(self.zone, self.region().zones, CLASS_NAME['EC2Zone'], id_) def getInstanceIds(self): return sorted(self.instances.objectIds()) def setInstanceIds(self, ids): updateToMany(relationship=self.instances, root=self.region().instances, type_=CLASS_NAME['EC2Instance'], ids=ids)
class Host(BaseComponent): meta_type = portal_type = "CloudStackHost" host_type = None host_state = None host_events = None host_version = None hypervisor = None capabilities = None created = None host_tags = None ip_address = None local_storage_active = None management_server_id = None _properties = BaseComponent._properties + ( {'id': 'host_type', 'type': 'string', 'mode': ''}, {'id': 'host_state', 'type': 'string', 'mode': ''}, {'id': 'host_events', 'type': 'string', 'mode': ''}, {'id': 'host_version', 'type': 'string', 'mode': ''}, {'id': 'hypervisor', 'type': 'string', 'mode': ''}, {'id': 'capabilities', 'type': 'string', 'mode': ''}, {'id': 'created', 'type': 'string', 'mode': ''}, {'id': 'host_tags', 'type': 'string', 'mode': ''}, {'id': 'ip_address', 'type': 'string', 'mode': ''}, {'id': 'local_storage_active', 'type': 'boolean', 'mode': ''}, {'id': 'management_server_id', 'type': 'int', 'mode': ''}, ) _relations = BaseComponent._relations + ( ('cluster', ToOne(ToManyCont, 'ZenPacks.zenoss.CloudStack.Cluster.Cluster', 'hosts') ), ('systemvms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.SystemVM.SystemVM', 'host') ), ('routervms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.RouterVM.RouterVM', 'host') ), ('vms', ToMany(ToOne, 'ZenPacks.zenoss.CloudStack.VirtualMachine.VirtualMachine', 'host') ), ) _catalogs = { 'HostCatalog': { 'deviceclass': '/CloudStack', 'indexes': { 'ipv4_addresses': {'type': 'keyword'}, }, }, } @property def ipv4_addresses(self): return (self.ip_address,) @classmethod def findByIP(cls, dmd, ipv4_addresses): ''' Return the first Host matching one of ipv4_addresses. ''' return next(cls.search( dmd, 'HostCatalog', ipv4_addresses=ipv4_addresses), None) def device(self): return self.cluster().device() def getManagedDevice(self): device = self.findDevice(self.ip_address) if device: return device ip = self.getDmdRoot("Networks").findIp(self.ip_address) if ip: return ip.device() @require_zenpack('ZenPacks.zenoss.XenServer') def xenserver_host(self): from ZenPacks.zenoss.XenServer.PIF import PIF pif = PIF.findByIP(self.dmd, self.ipv4_addresses) if pif: return pif.host()
class Host(BaseComponent): meta_type = portal_type = "oVirtHost" address = None status_state = None status_detail = None memory = None cpu_sockets = None cpu_cores = None cpu_name = None cpu_speed = None storage_manager = None _properties = BaseComponent._properties + ( { 'id': 'address', 'type': 'string', 'mode': 'w' }, { 'id': 'status_state', 'type': 'string', 'mode': 'w' }, { 'id': 'status_detail', 'type': 'string', 'mode': 'w' }, { 'id': 'memory', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_sockets', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_cores', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_name', 'type': 'string', 'mode': 'w' }, { 'id': 'cpu_speed', 'type': 'string', 'mode': 'w' }, { 'id': 'storage_manager', 'type': 'string', 'mode': 'w' }, ) _relations = BaseComponent._relations + ( ('cluster', ToOne(ToManyCont, 'ZenPacks.zenoss.oVirt.Cluster.Cluster', 'hosts')), ('nics', ToManyCont(ToOne, 'ZenPacks.zenoss.oVirt.HostNic.HostNic', 'host')), ('vms', ToMany(ToOne, 'ZenPacks.zenoss.oVirt.Vm.Vm', 'host')), ) def device(self): return self.cluster().device() def getIconPath(self): return icon_for(self.device(), 'host') def managed_device(self): macAddress = [nic.mac for nic in self.nics()] if not macAddress: return None cat = self.dmd.ZenLinkManager._getCatalog(layer=2) if cat is not None: for nic in self.nics(): if not nic.mac: continue # Use the first nic on a device, if we modelled the vm # this nic should already exist brains = cat(macaddress=nic.mac) if brains: for brain in brains: device = brain.getObject().device() if device: return device return None
class OSComponent(DeviceComponent, ManagedEntity): """ Logical Operating System component like a Process, IpInterface, etc. """ isUserCreatedFlag = False _relations = ManagedEntity._relations + ( ("links", ToMany(ToMany, "Products.ZenModel.Link", "endpoints")), ) def setUserCreateFlag(self): """ Sets self.isUserCreatedFlag to True. This indicated that the component was created by a user rather than via modelling. """ self.isUserCreatedFlag = True def isUserCreated(self): """ Returns the value of isUserCreated. See setUserCreatedFlag() above. """ return self.isUserCreatedFlag def device(self): """ Return our device object for DeviceResultInt. """ os = self.os() if os: return os.device() def manage_deleteComponent(self, REQUEST=None): """ Delete OSComponent """ url = None if REQUEST is not None: url = self.device().os.absolute_url_path() self.getPrimaryParent()._delObject(self.id) if REQUEST is not None: REQUEST['RESPONSE'].redirect(url) def manage_updateComponent(self, datamap, REQUEST=None): """ Update OSComponent """ url = None if REQUEST is not None: url = self.device().os.absolute_url_path() self.getPrimaryParent()._updateObject(self, datamap) if REQUEST is not None: REQUEST['RESPONSE'].redirect(url) def getPrettyLink(self): """ Gets a link to this object, plus an icon """ template = ("<a href='%s' class='prettylink'>" "<div class='device-icon-container'> " "<img class='device-icon' src='%s'/> " "</div>%s</a>") icon = self.getIconPath() href = self.getPrimaryUrlPath() name = self.titleOrId() return template % (href, icon, name)
class Host(PooledComponent): ''' Model class for Host. Also known as Server. ''' class_label = 'Host' class_plural_label = 'Hosts' meta_type = portal_type = 'XenServerHost' xenapi_metrics_ref = None api_version_major = None api_version_minor = None api_version_vendor = None address = None allowed_operations = None capabilities = None cpu_count = None cpu_speed = None edition = None enabled = None hostname = None name_description = None name_label = None sched_policy = None memory_total = None _properties = PooledComponent._properties + ( { 'id': 'xenapi_metrics_ref', 'label': 'XENAPI Metrics Reference', 'type': 'string', 'mode': 'w' }, { 'id': 'api_version_major', 'label': 'API Version Major', 'type': 'string', 'mode': 'w' }, { 'id': 'api_version_minor', 'label': 'API Version Minor', 'type': 'string', 'mode': 'w' }, { 'id': 'api_version_vendor', 'label': 'API Version Vendor', 'type': 'string', 'mode': 'w' }, { 'id': 'address', 'label': 'Address', 'type': 'string', 'mode': 'w' }, { 'id': 'allowed_operations', 'label': 'Allowed Operations', 'type': 'lines', 'mode': 'w' }, { 'id': 'capabilities', 'label': 'Capabilities', 'type': 'lines', 'mode': 'w' }, { 'id': 'cpu_count', 'label': 'CPU Count', 'type': 'int', 'mode': 'w' }, { 'id': 'cpu_speed', 'label': 'CPU Speed', 'type': 'float', 'mode': 'w' }, { 'id': 'edition', 'label': 'Edition', 'type': 'string', 'mode': 'w' }, { 'id': 'enabled', 'label': 'Enabled', 'type': 'boolean', 'mode': 'w' }, { 'id': 'hostname', 'label': 'Hostname', 'type': 'string', 'mode': 'w' }, { 'id': 'name_description', 'label': 'Description', 'type': 'string', 'mode': 'w' }, { 'id': 'name_label', 'label': 'Label', 'type': 'string', 'mode': 'w' }, { 'id': 'sched_policy', 'label': 'Scheduling Policy', 'type': 'string', 'mode': 'w' }, { 'id': 'memory_total', 'label': 'Total Memory', 'type': 'int', 'mode': 'w' }, ) _relations = PooledComponent._relations + ( ('endpoint', ToOne(ToManyCont, MODULE_NAME['Endpoint'], 'hosts')), ('hostcpus', ToManyCont(ToOne, MODULE_NAME['HostCPU'], 'host')), ('pbds', ToManyCont(ToOne, MODULE_NAME['PBD'], 'host')), ('pifs', ToManyCont(ToOne, MODULE_NAME['PIF'], 'host')), ('vms', ToMany(ToOne, MODULE_NAME['VM'], 'host')), ('master_for', ToOne(ToOne, MODULE_NAME['Pool'], 'master')), ('suspend_image_sr', ToOne(ToMany, MODULE_NAME['SR'], 'suspend_image_for_hosts')), ('crash_dump_sr', ToOne(ToMany, MODULE_NAME['SR'], 'crash_dump_for_hosts')), ('local_cache_sr', ToOne(ToMany, MODULE_NAME['SR'], 'local_cache_for_hosts')), ) @property def is_pool_master(self): return self.master_for() is not None @property def ipv4_addresses(self): return tuple( itertools.chain.from_iterable(x.ipv4_addresses for x in self.pifs() if x.ipv4_addresses)) @property def mac_addresses(self): return tuple(x.macaddress for x in self.pifs() if x.macaddress) @classmethod def objectmap(cls, ref, properties): ''' Return an ObjectMap given XenAPI host ref and properties. ''' if 'uuid' not in properties: return { 'relname': 'hosts', 'id': id_from_ref, } title = properties.get('name_label') or properties.get('hostname') cpu_info = properties.get('cpu_info', {}) cpu_speed = float_or_none(cpu_info.get('speed')) if cpu_speed: cpu_speed = cpu_speed * 1048576 # Convert from MHz to Hz. return { 'relname': 'hosts', 'id': id_from_ref(ref), 'title': title, 'xenapi_ref': ref, 'xenapi_uuid': properties.get('uuid'), 'xenapi_metrics_ref': properties.get('metrics'), 'api_version_major': properties.get('API_version_major'), 'api_version_minor': properties.get('API_version_minor'), 'api_version_vendor': properties.get('API_version_vendor'), 'address': properties.get('address'), 'allowed_operations': properties.get('allowed_operations'), 'capabilities': properties.get('capabilities'), 'cpu_count': int_or_none(cpu_info.get('cpu_count')), 'cpu_speed': cpu_speed, 'edition': properties.get('edition'), 'enabled': properties.get('enabled'), 'hostname': properties.get('hostname'), 'name_description': properties.get('name_description'), 'name_label': properties.get('name_label'), 'sched_policy': properties.get('sched_policy'), 'setVMs': ids_from_refs(properties.get('resident_VMs', [])), 'setSuspendImageSR': id_from_ref(properties.get('suspend_image_sr')), 'setCrashDumpSR': id_from_ref(properties.get('crash_dump_sr')), 'setLocalCacheSR': id_from_ref(properties.get('local_cache_sr')), } @classmethod def objectmap_metrics(cls, ref, properties): ''' Return an ObjectMap given XenAPI host ref and host_metrics properties. ''' return { 'relname': 'hosts', 'id': id_from_ref(ref), 'memory_total': int_or_none(properties.get('memory_total')), } def getVMs(self): ''' Return a sorted list of each vm id related to this host. Used by modeling. ''' return sorted(vm.id for vm in self.vms.objectValuesGen()) def setVMs(self, vm_ids): ''' Update VM relationship given ids. Used by modeling. ''' updateToMany(relationship=self.vms, root=self.device(), type_=CLASS_NAME['VM'], ids=vm_ids) def getMasterFor(self): ''' Return Pool id or None. Used by modeling. ''' master_for = self.master_for() if master_for: return master_for.id def setMasterFor(self, pool_id): ''' Set master_for relationship by Pool id. Used by modeling. ''' updateToOne(relationship=self.master_for, root=self.device(), type_=CLASS_NAME['Pool'], id_=pool_id) def getSuspendImageSR(self): ''' Return SR id or None. Used by modeling. ''' suspend_image_sr = self.suspend_image_sr() if suspend_image_sr: return suspend_image_sr.id def setSuspendImageSR(self, sr_id): ''' Set suspend_image_sr relationship by SR id. Used by modeling. ''' updateToOne(relationship=self.suspend_image_sr, root=self.device(), type_=CLASS_NAME['SR'], id_=sr_id) def getCrashDumpSR(self): ''' Return SR id or None. Used by modeling. ''' crash_dump_sr = self.crash_dump_sr() if crash_dump_sr: return crash_dump_sr.id def setCrashDumpSR(self, sr_id): ''' Set crash_dump_sr relationship by SR id. Used by modeling. ''' updateToOne(relationship=self.crash_dump_sr, root=self.device(), type_=CLASS_NAME['SR'], id_=sr_id) def getLocalCacheSR(self): ''' Return SR id or None. Used by modeling. ''' local_cache_sr = self.local_cache_sr() if local_cache_sr: return local_cache_sr.id def setLocalCacheSR(self, sr_id): ''' Set local_cache_sr relationship by SR id. Used by modeling. ''' updateToOne(relationship=self.local_cache_sr, root=self.device(), type_=CLASS_NAME['SR'], id_=sr_id) def xenrrd_prefix(self): ''' Return prefix under which XenServer stores RRD data about this component. ''' if self.xenapi_uuid: return ('host', self.xenapi_uuid, '') def getIconPath(self): ''' Return URL to icon representing objects of this class. ''' return '/++resource++xenserver/img/host.png' def server_device(self): ''' Return the associated device on which this host runs. Zenoss may also be monitoring the XenServer host as a normal Linux server. This method will attempt to find that device by matching the XenServer host's PIF MAC addresses then IP addresses with those of other monitored devices. ''' macaddresses = [x.macaddress for x in self.pifs() if x.macaddress] if macaddresses: for iface in findIpInterfacesByMAC(self.dmd, macaddresses): return iface.device() if self.address: ip = self.endpoint.getNetworkRoot().findIp(self.address) if ip: device = ip.device() if device: return device @require_zenpack('ZenPacks.zenoss.CloudStack') def cloudstack_host(self): ''' Return the associated CloudStack host. ''' from ZenPacks.zenoss.CloudStack.Host import Host try: return Host.findByIP(self.dmd, self.ipv4_addresses) except AttributeError: # The CloudStack Host class didn't gain the findByIP method # until version 1.1 of the ZenPack. pass