async def _get_cached_klist(self): """ Try to get retrieve cached kerberos tgt info. If it hasn't been cached, perform klist, parse it, put it in cache, then return it. """ if await self.middleware.call('cache.has_key', 'KRB_TGT_INFO'): return (await self.middleware.call('cache.get', 'KRB_TGT_INFO')) ad = await self.middleware.call('activedirectory.config') ldap = await self.middleware.call('ldap.config') ad_TGT = [] ldap_TGT = [] parsed_klist = {} if not ad['enable'] and not ldap['enable']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not ad['enable'] and not ldap['kerberos_realm']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not await self.status(): await self.start() krb5 = KRB5.platform() try: if krb5 == KRB5.HEIMDAL: klist = await asyncio.wait_for(run(['klist', '-v'], check=False, stdout=subprocess.PIPE), timeout=10.0) else: klist = await asyncio.wait_for(run(['klist', '-ef'], check=False, stdout=subprocess.PIPE), timeout=10.0) except Exception as e: await self.stop() raise CallError( "Attempt to list kerberos tickets failed with error: %s", e) if klist.returncode != 0: await self.stop() raise CallError( f'klist failed with error: {klist.stderr.decode()}') klist_output = klist.stdout.decode() parsed_klist = await self.parse_klist({ "krb5type": krb5.value, "klistin": klist_output, "ad": ad, "ldap": ldap, }) if parsed_klist['ad_TGT'] or parsed_klist['ldap_TGT']: await self.middleware.call('cache.put', 'KRB_TGT_INFO', parsed_klist) return parsed_klist
async def power_management(self, dev, disk=None): """ Actually sets power management for `dev`. `disk` is the disk.query entry and optional so this can be called only with disk name. """ if not disk: disk = await self.middleware.call('disk.query', [('name', '=', dev)]) if not disk: return disk = disk[0] try: identify = (await run('camcontrol', 'identify', dev)).stdout.decode() except subprocess.CalledProcessError: return # Try to set APM if RE_CAMCONTROL_APM.search(identify): args = ['camcontrol', 'apm', dev] if disk['advpowermgmt'] != 'DISABLED': args += ['-l', disk['advpowermgmt']] asyncio.ensure_future(run(*args, check=False)) # Try to set AAM if RE_CAMCONTROL_AAM.search(identify): acousticlevel_map = { 'MINIMUM': '1', 'MEDIUM': '64', 'MAXIMUM': '127', } asyncio.ensure_future(run( 'camcontrol', 'aam', dev, '-l', acousticlevel_map.get(disk['acousticlevel'], '0'), check=False, )) # Try to set idle if RE_CAMCONTROL_POWER.search(identify): if disk['hddstandby'] != 'ALWAYS ON': # database is in minutes, camcontrol uses seconds idle = int(disk['hddstandby']) * 60 else: idle = 0 # We wait a minute before applying idle because its likely happening during system boot # or some activity is happening very soon. async def camcontrol_idle(): await asyncio.sleep(60) asyncio.ensure_future(run('camcontrol', 'idle', dev, '-t', str(idle), check=False)) asyncio.ensure_future(camcontrol_idle())
async def renew(self): """ Compare timestamp of cached TGT info with current timestamp. If we're within 5 minutes of expire time, renew the TGT via 'kinit -R'. """ tgt_info = await self._get_cached_klist() ret = True must_renew = False must_reinit = False if not tgt_info['ad_TGT'] and not tgt_info['ldap_TGT']: must_reinit = True if tgt_info['ad_TGT']: permitted_buffer = datetime.timedelta(minutes=5) current_time = datetime.datetime.now() for entry in tgt_info['ad_TGT']: tgt_expiry_time = datetime.datetime.fromtimestamp( time.mktime(entry['expires'])) delta = tgt_expiry_time - current_time if datetime.timedelta(minutes=0) > delta: must_reinit = True break if permitted_buffer > delta: must_renew = True break if tgt_info['ldap_TGT']: permitted_buffer = datetime.timedelta(minutes=5) current_time = datetime.datetime.now() for entry in tgt_info['ldap_TGT']: tgt_expiry_time = datetime.datetime.fromtimestamp( time.mktime(entry['expires'])) delta = tgt_expiry_time - current_time if datetime.timedelta(minutes=0) > delta: must_reinit = True break if permitted_buffer > delta: must_renew = True break if must_renew and not must_reinit: try: kinit = await asyncio.wait_for(run(['kinit', '-R'], check=False), timeout=15) if kinit.returncode != 0: raise CallError( f'kinit -R failed with error: {kinit.stderr.decode()}') self.logger.debug('Successfully renewed kerberos TGT') await self.middleware.call('cache.pop', 'KRB_TGT_INFO') except asyncio.TimeoutError: self.logger.debug( 'Attempt to renew kerberos TGT failed after 15 seconds.') if must_reinit: ret = await self.start() await self.middleware.call('cache.pop', 'KRB_TGT_INFO') return ret
async def power_management_impl(self, dev, disk): asyncio.ensure_future( run( 'hdparm', '-B', disk['advpowermgmt'] if disk['advpowermgmt'] != 'DISABLED' else '255', f'/dev/{dev}', check=False, )) if disk['hddstandby'] != 'ALWAYS ON': if int(disk['hddstandby']) <= 20: # Values from 1 to 240 specify multiples of 5 seconds idle = int(int(disk['hddstandby']) * 60 / 5) else: # values from 241 to 251 specify multiples of 30 minutes. idle = 240 + int(int(disk['hddstandby']) / 30) else: idle = 0 # We wait a minute before applying idle because its likely happening during system boot # or some activity is happening very soon. async def camcontrol_idle(): await asyncio.sleep(60) asyncio.ensure_future( run('hdparm', '-S', str(idle), f'/dev/{dev}', check=False)) asyncio.ensure_future(camcontrol_idle())
async def power_management_impl(self, dev, disk): try: identify = (await run('camcontrol', 'identify', dev)).stdout.decode() except subprocess.CalledProcessError: return # Try to set APM if RE_CAMCONTROL_APM.search(identify): args = ['camcontrol', 'apm', dev] if disk['advpowermgmt'] != 'DISABLED': args += ['-l', disk['advpowermgmt']] asyncio.ensure_future(run(*args, check=False)) # Try to set idle if RE_CAMCONTROL_POWER.search(identify): if disk['hddstandby'] != 'ALWAYS ON': # database is in minutes, camcontrol uses seconds idle = int(disk['hddstandby']) * 60 else: idle = 0 # We wait a minute before applying idle because its likely happening during system boot # or some activity is happening very soon. async def camcontrol_idle(): await asyncio.sleep(60) asyncio.ensure_future(run('camcontrol', 'idle', dev, '-t', str(idle), check=False)) asyncio.ensure_future(camcontrol_idle())
async def camcontrol_idle(): await asyncio.sleep(60) asyncio.ensure_future( run('camcontrol', 'idle', dev, '-t', str(idle), check=False))
async def renew(self): """ Compare timestamp of cached TGT info with current timestamp. If we're within 5 minutes of expire time, renew the TGT via 'kinit -R'. """ tgt_info = await self._get_cached_klist() ret = True must_renew = False must_reinit = False if not tgt_info['ad_TGT'] and not tgt_info['ldap_TGT']: must_reinit = True if tgt_info['ad_TGT']: permitted_buffer = datetime.timedelta(minutes=5) current_time = datetime.datetime.now() for entry in tgt_info['ad_TGT']: tgt_expiry_time = datetime.datetime.fromtimestamp(time.mktime(entry['expires'])) delta = tgt_expiry_time - current_time if datetime.timedelta(minutes=0) > delta: must_reinit = True break if permitted_buffer > delta: must_renew = True break if tgt_info['ldap_TGT']: permitted_buffer = datetime.timedelta(minutes=5) current_time = datetime.datetime.now() for entry in tgt_info['ldap_TGT']: tgt_expiry_time = datetime.datetime.fromtimestamp(time.mktime(entry['expires'])) delta = tgt_expiry_time - current_time if datetime.timedelta(minutes=0) > delta: must_reinit = True break if permitted_buffer > delta: must_renew = True break if must_renew and not must_reinit: try: kinit = await asyncio.wait_for(run(['/usr/bin/kinit', '-R'], check=False), timeout=15) if kinit.returncode != 0: raise CallError(f'kinit -R failed with error: {kinit.stderr.decode()}') self.logger.debug(f'Successfully renewed kerberos TGT') await self.middleware.call('cache.pop', 'KRB_TGT_INFO') except asyncio.TimeoutError: self.logger.debug('Attempt to renew kerberos TGT failed after 15 seconds.') if must_reinit: ret = await self.start() await self.middleware.call('cache.pop', 'KRB_TGT_INFO') return ret
async def _get_cached_klist(self): """ Try to get retrieve cached kerberos tgt info. If it hasn't been cached, perform klist, parse it, put it in cache, then return it. """ if await self.middleware.call('cache.has_key', 'KRB_TGT_INFO'): return (await self.middleware.call('cache.get', 'KRB_TGT_INFO')) ad = await self.middleware.call('activedirectory.config') ldap = await self.middleware.call('ldap.config') ad_TGT = [] ldap_TGT = [] if not ad['enable'] and not ldap['enable']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not ad['enable'] and not ldap['kerberos_realm']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not await self.status(): await self.start() try: klist = await asyncio.wait_for( run(['/usr/bin/klist', '-v'], check=False, stdout=subprocess.PIPE), timeout=10.0 ) except Exception as e: await self.stop() raise CallError("Attempt to list kerberos tickets failed with error: %s", e) if klist.returncode != 0: await self.stop() raise CallError(f'klist failed with error: {klist.stderr.decode()}') klist_output = klist.stdout.decode() tkts = klist_output.split('\n\n') for tkt in tkts: s = tkt.splitlines() if len(s) > 4: for entry in s: if "Auth time" in entry: issued = time.strptime((entry.split('Auth time: '))[1].lstrip().replace(' ', ' '), '%b %d %H:%M:%S %Y') elif "End time" in entry: expires = time.strptime((entry.split('End time: '))[1].lstrip().replace(' ', ' '), '%b %d %H:%M:%S %Y') elif "Server" in entry: server = (entry.split('Server: '))[1] elif "Client" in entry: client = (entry.split('Client: '))[1] elif 'Ticket etype' in entry: etype = (entry.split('Ticket etype: '))[1] elif 'Ticket flags' in entry: flags = (entry.split('Ticket flags: '))[1].split(',') if ad['enable'] and ad['kerberos_realm'] and ad['domainname'] in client: ad_TGT.append({ 'issued': issued, 'expires': expires, 'client': client, 'server': server, 'etype': etype, 'flags': flags, }) elif ldap['enable'] and ldap['kerberos_realm']: if ldap['kerberos_realm']['krb_realm'] in client: ldap_TGT.append({ 'issued': issued, 'expires': expires, 'client': client, 'server': server, 'etype': etype, 'flags': flags, }) if ad_TGT or ldap_TGT: await self.middleware.call('cache.put', 'KRB_TGT_INFO', {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT}) return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT}
async def _get_cached_klist(self): """ Try to get retrieve cached kerberos tgt info. If it hasn't been cached, perform klist, parse it, put it in cache, then return it. """ if await self.middleware.call('cache.has_key', 'KRB_TGT_INFO'): return (await self.middleware.call('cache.get', 'KRB_TGT_INFO')) ad = await self.middleware.call('activedirectory.config') ldap = await self.middleware.call('ldap.config') ad_TGT = [] ldap_TGT = [] if not ad['enable'] and not ldap['enable']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not ad['enable'] and not ldap['kerberos_realm']: return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT} if not await self.status(): await self.start() try: klist = await asyncio.wait_for(run(['/usr/bin/klist', '-v'], check=False, stdout=subprocess.PIPE), timeout=10.0) except Exception as e: await self.stop() raise CallError( "Attempt to list kerberos tickets failed with error: %s", e) if klist.returncode != 0: await self.stop() raise CallError( f'klist failed with error: {klist.stderr.decode()}') klist_output = klist.stdout.decode() tkts = klist_output.split('\n\n') for tkt in tkts: s = tkt.splitlines() if len(s) > 4: for entry in s: if "Auth time" in entry: issued = time.strptime( (entry.split('Auth time: '))[1].lstrip().replace( ' ', ' '), '%b %d %H:%M:%S %Y') elif "End time" in entry: expires = time.strptime( (entry.split('End time: '))[1].lstrip().replace( ' ', ' '), '%b %d %H:%M:%S %Y') elif "Server" in entry: server = (entry.split('Server: '))[1] elif "Client" in entry: client = (entry.split('Client: '))[1] elif 'Ticket etype' in entry: etype = (entry.split('Ticket etype: '))[1] elif 'Ticket flags' in entry: flags = (entry.split('Ticket flags: '))[1].split(',') if ad['enable'] and ad['kerberos_realm'] and ad[ 'domainname'] in client: ad_TGT.append({ 'issued': issued, 'expires': expires, 'client': client, 'server': server, 'etype': etype, 'flags': flags, }) elif ldap['enable'] and ldap['kerberos_realm']: if ldap['kerberos_realm']['krb_realm'] in client: ldap_TGT.append({ 'issued': issued, 'expires': expires, 'client': client, 'server': server, 'etype': etype, 'flags': flags, }) if ad_TGT or ldap_TGT: await self.middleware.call('cache.put', 'KRB_TGT_INFO', { 'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT }) return {'ad_TGT': ad_TGT, 'ldap_TGT': ldap_TGT}
async def camcontrol_idle(): await asyncio.sleep(60) asyncio.ensure_future( run('hdparm', '-S', str(idle), f'/dev/{dev}', check=False))