def run(self): alerts = [] for vol in Volume.objects.filter(vol_fstype='ZFS'): if vol.is_upgraded is not True: alerts.append(Alert( Alert.WARN, _( 'New feature flags are available for volume %s. Refer ' 'to the "Upgrading a ZFS Pool" section of the User ' 'Guide for instructions.' ) % vol.vol_name, )) proc = subprocess.Popen( "zfs upgrade | grep FILESYSTEM", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) output = proc.communicate()[0].strip(' ').strip('\n') if output: alerts.append(Alert(Alert.WARN, _( 'ZFS filesystem version is out of date. Consider upgrading' ' using "zfs upgrade" command line.' ))) return alerts
def run(self): if not os.path.exists(LICENSE_FILE): return None with open(LICENSE_FILE, 'rb') as f: data = f.read() try: license = License.load(data) except: return [Alert( Alert.CRIT, _('Unable to decode %s license') % get_sw_name(), )] end_date = license.contract_end if end_date < datetime.now().date(): return [Alert( Alert.CRIT, _('Your %s license has expired') % get_sw_name(), )] elif end_date - timedelta(days=30) < datetime.now().date(): return [Alert( Alert.WARN, _( 'Your %(sw_name)s license is going to expire in %(date)s' ) % { 'sw_name': get_sw_name(), 'date': end_date, } )]
def run(self): alerts = [] if os.path.exists('/tmp/alert_invalid_ssl_nginx'): msg = 'HTTP SSL certificate is not valid, failling back to HTTP' try: open('/tmp/alert_invalid_ssl_nginx').read().split()[0] msg = 'FreeNAS does not support certificates with keys shorter than 1024 bits. HTTPS will not be enabled until a certificate having at least 1024 bit keylength is provided' except IndexError: pass alerts.append(Alert(Alert.WARN, msg)) for cert_name in glob.glob("/var/tmp/alert_invalidcert_*"): alerts.append( Alert( Alert.WARN, _('The Certificate: %(cert_name)s is either malformed ' 'or invalid and cannot be used for any services. This ' 'Alert will remain here until the certificate is deleted' ) % {'cert_name': cert_name.split('_', 2)[-1]})) for CA_name in glob.glob("/var/tmp/alert_invalidCA_*"): alerts.append( Alert( Alert.WARN, _('The Certificate Authority(CA): %(CA_name)s is either ' 'malformed or invalid and cannot be used for any services.' ' This Alert will remain here until the CA is deleted') % {'CA_name': CA_name.split('_', 2)[-1]})) return alerts
def run(self): if not Volume.objects.all().exists(): return None if ( hasattr(notifier, 'failover_status') and notifier().failover_status() == 'BACKUP' ): return None systemdataset, basename = notifier().system_dataset_settings() if not systemdataset.sys_pool: return [ Alert( Alert.WARN, "No system pool configured, please configure one in " "Settings->System Dataset->Pool" ), ] if os.path.exists('/var/db/samba4/.alert_cant_migrate'): return [ Alert( Alert.WARN, "Multiple legacy samba4 datasets detected. Auto-migration " "to /mnt/%s/.system/samba4 cannot be done. Please perform " "this step manually and then delete the now-obsolete " "samba4 datasets and /var/db/samba4/.alert_cant_migrate" % systemdataset.sys_pool ), ]
def run(self): alerts = [] mps = defaultdict(dict) for o in sysctl.filter('dev.mps'): mibs = o.name.split('.', 3) if len(mibs) < 4: continue number, mib = mibs[2:4] try: major = int(o.value.split('.', 1)[0]) mps[number][mib] = major except: continue for number, mibs in list(mps.items()): firmware = mibs.get('firmware_version') driver = mibs.get('driver_version') try: # Broadcom added a new one for us, an allowed combo is p20 firmware and v21 driver # https://bugs.freenas.org/issues/16649 if ((int(firmware) != int(driver)) and not (int(firmware) == 20 and int(driver) == 21)): alerts.append( Alert( Alert.WARN, _('Firmware version %(fwversion)s does not match driver ' 'version %(drversion)s for /dev/mps%(mps)s. Please ' 'flash controller to P%(drversion)s IT firmware.' ) % { 'fwversion': firmware, 'drversion': driver, 'mps': number, })) except ValueError: # cast returned Cthulhu # This shouldn't ever happen but as a fallback try the old method if ((firmware != driver) and not (firmware.startswith("20") and driver.startswith("21"))): alerts.append( Alert( Alert.WARN, _('Firmware version %(fwversion)s does not match driver ' 'version %(drversion)s for /dev/mps%(mps)s') % { 'fwversion': firmware, 'drversion': driver, 'mps': number, })) return alerts
def on_volume_status_not_healthy(self, status, message): if message: return Alert( Alert.WARN, _('The boot volume status is %(status)s:' ' %(message)s') % { 'status': status, 'message': message, }) else: return Alert( Alert.WARN, _('The boot volume status is %(status)s') % { 'status': status, })
def run(self): alerts = [] if not os.path.exists(SMART_FILE): return alerts lock = LockFile(SMART_FILE) while not lock.i_am_locking(): try: lock.acquire(timeout=5) except LockTimeout: return alerts with open(SMART_FILE, 'rb') as f: try: data = pickle.loads(f.read()) except: data = {} msg = '' for msgs in data.itervalues(): if not msgs: continue msg += '<br />\n'.join(msgs) if msg: alerts.append(Alert(Alert.CRIT, msg)) lock.release() return alerts
def run(self): alerts = [] systemname = pipeopen( "/usr/local/sbin/dmidecode -s system-product-name").communicate( )[0].strip() boardname = pipeopen( "/usr/local/sbin/dmidecode -s baseboard-product-name").communicate( )[0].strip() if 'freenas' in systemname.lower() and boardname == 'C2750D4I': mcinfo = pipeopen( "/usr/local/bin/ipmitool mc info").communicate()[0] reg = re.search(r'Firmware Revision.*: (\S+)', mcinfo, flags=re.M) if not reg: return alerts fwver = reg.group(1) try: fwver = [int(i) for i in fwver.split('.')] except ValueError: log.warn( 'Failed to parse BMC firmware version: {}'.format(fwver)) return alerts if len(fwver) < 2 or not (fwver[0] == 0 and fwver[1] < 30): return alerts alerts.append( Alert( Alert.CRIT, _('FreeNAS Mini Critical IPMI Firmware Update - Your ' 'Mini has an available IPMI firmware update, please ' 'click <a href="%s" target="_blank">here</a> for ' 'installation instructions') % 'https://support.ixsystems.com/index.php?/Knowledgebase/Article/View/287', )) return alerts
def run(self): alerts = [] if not os.path.exists(COLLECTD_FILE): return alerts lock = LockFile(COLLECTD_FILE) while not lock.i_am_locking(): try: lock.acquire(timeout=5) except LockTimeout: return alerts with open(COLLECTD_FILE, 'rb') as f: try: data = pickle.loads(f.read()) except: data = {} lock.release() for k, v in list(data.items()): if v['Severity'] == 'WARNING': l = Alert.WARN else: l = Alert.CRIT if k == 'ctl-ha/disk_octets': msg = "CTL HA link is actively used, check initiators connectivity" else: msg = k alerts.append(Alert(l, msg)) return alerts
def run(self): alerts = [] mpr = defaultdict(dict) for o in sysctl.filter('dev.mpr'): mibs = o.name.split('.', 3) if len(mibs) < 4: continue number, mib = mibs[2:4] try: major = int(o.value.split('.', 1)[0]) mpr[number][mib] = major except: continue for number, mibs in mpr.items(): firmware = mibs.get('firmware_version') driver = mibs.get('driver_version') if firmware != driver: alerts.append( Alert( Alert.WARN, _('Firmware version %(fwversion)s does not match driver ' 'version %(drversion)s for /dev/mpr%(mpr)s') % { 'fwversion': firmware, 'drversion': driver, 'mpr': number, })) return alerts
def run(self): alerts = [] if not os.path.exists(SMART_FILE): return alerts lock = LockFile(SMART_FILE) while not lock.i_am_locking(): try: lock.acquire(timeout=5) except LockTimeout: return alerts with open(SMART_FILE, 'rb') as f: try: data = pickle.loads(f.read()) except: data = {} for msgs in data.itervalues(): if not msgs: continue for msg in msgs: if msg is None: continue alerts.append(Alert(Alert.CRIT, msg, hardware=True)) lock.release() return alerts
def run(self): alerts = [] try: update = Update.objects.order_by('-id')[0] except IndexError: update = Update.objects.create() path = notifier().system_dataset_path() if not path: return None try: check = CheckForUpdates(train=update.get_train(), cache_dir=path) except: check = None if check: alerts.append( Alert( Alert.OK, _( 'There is a new update available! Apply it in System ' '-> Update tab.' ), ) ) return alerts
def run(self): alerts = [] try: update = Update.objects.order_by('-id')[0] except IndexError: update = Update.objects.create() path = notifier().get_update_location() if not path: return None try: updates = PendingUpdates(path) except: updates = None if updates: alerts.append( Alert( Alert.OK, _( 'There is a new update available! Apply it in System ' '-> Update tab.' ), ) ) return alerts
def run(self): alerts = [] if (services.objects.get(srv_service='smartd').srv_enable): # sysctl kern.vm_guest will return a hypervisor name, or the string "none" if FreeNAS is running on bare iron. p0 = subprocess.Popen(["/sbin/sysctl", "-n", "kern.vm_guest"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8') status = p0.communicate()[0].strip() # This really isn't confused with python None if status != "none": # We got something other than "none", maybe "vmware", "xen", "vbox". Regardless, smartd not running # in these environments isn't a huge deal. So we'll skip alerting. return None if hasattr(notifier, 'failover_status' ) and notifier().failover_status() != 'MASTER': return None p1 = subprocess.Popen(["/usr/sbin/service", "smartd", "status"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8') status = p1.communicate()[0] if p1.returncode == 1: alerts.append(Alert(Alert.WARN, status)) else: return None else: return None return alerts
def on_volume_status_not_healthy(self, state, status): return Alert( Alert.CRIT, _('The boot volume state is %(state)s: %(status)s') % { 'state': state, 'status': status, })
def run(self): alerts = [] mps = defaultdict(dict) for o in sysctl.filter('dev.mps'): mibs = o.name.split('.', 3) if len(mibs) < 4: continue number, mib = mibs[2:4] try: major = int(o.value.split('.', 1)[0]) mps[number][mib] = major except: continue for number, mibs in mps.items(): firmware = mibs.get('firmware_version') driver = mibs.get('driver_version') try: if int(firmware) != int(driver): alerts.append( Alert( Alert.WARN, _('Firmware version %(fwversion)s does not match driver ' 'version %(drversion)s for /dev/mps%(mps)s. Please ' 'flash controller to P%(drversion)s IT firmware.' ) % { 'fwversion': firmware, 'drversion': driver, 'mps': number, })) except ValueError: # cast returned cthulu # This shouldn't ever happen but as a fallback try the old method if firmware != driver: alerts.append( Alert( Alert.WARN, _('Firmware version %(fwversion)s does not match driver ' 'version %(drversion)s for /dev/mps%(mps)s') % { 'fwversion': firmware, 'drversion': driver, 'mps': number, })) return alerts
def on_volume_status_not_healthy(self, vol, state, status): return Alert(Alert.CRIT, _( 'The volume %(volume)s state is %(state)s: %(status)s' ) % { 'volume': vol, 'state': state, 'status': status, })
def run(self): if os.path.exists('/tmp/alert_invalid_ssl_nginx'): return [ Alert( Alert.WARN, 'HTTP SSL certificate is not valid, failling back to HTTP' ), ]
def run(self): alerts = [] if os.path.exists('/tmp/.ldap_status_alert'): alerts.append(Alert(Alert.WARN, "LDAP did not bind to the domain")) return alerts
def run(self): alerts = [] if os.path.exists(GELI_REKEY_FAILED): alerts.append(Alert(Alert.CRIT, _( 'Encrypted volume failed to rekey some disks. Please make ' 'sure you have working recovery keys, check logs files and ' 'correct the error as it may result to data loss.' ), hardware=True)) return alerts
def run(self): if os.path.exists('/tmp/.nfsbindip_notfound'): return [ Alert( Alert.WARN, _('NFS services could not bind specific IPs, using wildcard' ), ) ]
def run(self): alerts = [] if os.path.exists('/tmp/.adalert'): alerts.append( Alert(Alert.WARN, "ActiveDirectory did not bind to the domain")) return alerts
def run(self): alerts = [] if os.path.exists('/data/update.failed'): alerts.append( Alert( Alert.CRIT, _('Update failed. Check /data/update.failed for further ' 'details.'), )) return alerts
def run(self): alerts = [] for iface in netif.list_interfaces().values(): if not isinstance(iface, netif.LaggInterface): continue active = [] inactive = [] for name, flags in iface.ports: if netif.LaggPortFlags.ACTIVE not in flags: inactive.append(name) else: active.append(name) # ports that are not ACTIVE and LACP if inactive and iface.protocol == netif.AggregationProtocol.LACP: # Only alert if this has happened more than twice, see #24160 self.__count[iface.name] += 1 if self.__count[iface.name] > 2: alerts.append( Alert( Alert.CRIT, _('These ports are not ACTIVE on LAGG interface %(name)s: %(ports)s. Please check cabling and switch.' ) % { 'name': iface.name, 'ports': ', '.join(inactive) }, )) # For FAILOVER protocol we should have one ACTIVE port elif len( active ) != 1 and iface.protocol == netif.AggregationProtocol.FAILOVER: # Only alert if this has happened more than twice, see #24160 self.__count[iface.name] += 1 if self.__count[iface.name] > 2: alerts.append( Alert( Alert.CRIT, _('There are no ACTIVE ports on LAGG interface %(name)s. Please check cabling and switch.' ) % {'name': iface.name}, )) else: self.__count[iface.name] = 0 return alerts
def run(self): if os.path.exists('/tmp/alert_invalid_ssl_nginx'): msg = 'HTTP SSL certificate is not valid, failling back to HTTP' try: a = open('/tmp/alert_invalid_ssl_nginx').read().split()[0] msg = 'FreeNAS does not support certificates with keys shorter than 1024 bits. HTTPS will not be enabled until a certificate having at least 1024 bit keylength is provided' except IndexError: pass return [ Alert(Alert.WARN, msg), ]
def run(self): if not os.path.exists(PORTAL_IP_FILE): return None with open(PORTAL_IP_FILE) as f: ips = f.read().split('\n') ips = filter(lambda y: bool(y), ips) return [ Alert( Alert.WARN, _('The following IPs are bind to iSCSI Portal but were not' ' found in the system: %s') % (', '.join(ips))) ]
def run(self): alerts = [] regexp = re.compile(r"\[(.*)\] (.*)") if os.path.exists(ALERT_FILE): with open(ALERT_FILE) as f: for line in f: line = line.rstrip() # Line looks like [PASS|FAIL]<text>, maybe other tags match = regexp.match(line) lvl = Alert.WARN if match: if match.group(1) in (TEST_WARNING): lvl = Alert.WARN elif match.group(1) in (TEST_FAIL, TEST_CRITICAL): lvl = Alert.CRIT elif match.group(1) in (TEST_PASS): lvl = Alert.OK alerts.append(Alert(lvl, match.group(2))) else: alerts.append(Alert(lvl, line)) return alerts
def run(self): alerts = [] for file in os.listdir("/tmp/"): if file.endswith(".service_monitor"): full_path = '/tmp/' + file with open(full_path, 'r') as _file: for alert_line in _file: alerts.append(Alert(Alert.WARN, alert_line)) return alerts
def run(self): not_optimal = [] for mp in notifier().multipath_all(): if mp.status != 'OPTIMAL': not_optimal.append(mp.name) if not_optimal: return [ Alert( Alert.CRIT, _('The following multipaths are not optimal: %s') % (', '.join(not_optimal), )) ]
def run(self): alerts = [] for vol in Volume.objects.filter(vol_fstype='ZFS'): if vol.is_upgraded is not True: alerts.append( Alert( Alert.WARN, _('New feature flags are available for volume %s. Refer ' 'to the "Upgrading a ZFS Pool" section of the User ' 'Guide for instructions.') % vol.vol_name, )) return alerts