def check_year(server_id): """ lmutil.exe does not provide a year with license data, this is a work-around to account for that. Checks in all licences if there is a difference between current year and the year of any checked out licenses. :param server_id: Id of server """ checked_out = History.time_in_none(server_id) for r in checked_out: if datetime.now().year != r.time_out.year: Product.reset(server_id) History.reset(server_id) break
def run(): """ Entry point for updating licenses. This script can optionally be run stand alone (cron job or windows task scheduler). Relies on the lmutil.exe to collect server information. """ checked_out_history_ids = [] error = False try: for server in license_servers: print('Reading from {} on port {}...'.format( server['name'], server['port'])) s = server['name'] port = server['port'] info = None status = None server_id = Server.upsert(server) update_id = Updates.start(server_id) check_year(server_id) try: # Server info lm_util_lines = os.popen(lm_util + " lmstat -c " + port + "@" + s).readlines() if len(lm_util_lines) == 0: m = 'Unable to read license data. Check path to lmutil.exe and license server parameters are correct.' raise Exception(m) for idx, line in enumerate(lm_util_lines): l = line.split(':') if 'error' in line.lower(): raise Exception(line) elif status is None: if l[0] == s: info = l[1].strip() if 'license server up' in info.lower(): status = 'OK' info = None else: raise Exception( 'Unable to parse license data. Check license server is functioning properly.' ) elif (idx + 1) == len(lm_util_lines) and status is None: raise Exception('No license data from lmutil.exe') except Exception as e: reset(update_id, server_id, str(e)) error = True continue try: # Product info for idx, val in enumerate(products): lm_util_lines = os.popen(lm_util + " lmstat -f " + val['internal-name'] + " -c " + port + "@" + s).readlines() for idx, line in enumerate(lm_util_lines): if 'Users of ' + val['internal-name'] in line: lic = line.lower().split('total of ') lic_total = int(lic[1][:2]) lic_out = int(lic[2][:2]) Product.upsert(server_id=server_id, internal_name=val['internal-name'], common_name=val['common-name'], category=val['category'], type=val['type'], license_out=lic_out, license_total=lic_total) # User info if ") (" + s + "/" + port in line: cols = line.split() if 'activated' in line.lower(): user = '******' computer = cols[2] else: user = cols[0] computer = cols[1] # Format date for sql month = cols[-2].split("/")[0] day = cols[-2].split("/")[1] if len(day) == 1: day = '0' + day if len(month) == 1: month = '0' + month t = cols[-1] hour = t.split(":")[0] min = t.split(":")[1] date_4_db = datetime(datetime.now().year, int(month), int(day), int(hour), int(min)) workstation_id = Workstation.add( workstation=computer) user_id = User.add(username=user) product_id = Product.query(val['internal-name'], server_id) history_id = History.add(user_id, workstation_id, server_id, product_id, update_id, date_4_db) checked_out_history_ids.append(history_id) dt = datetime.now().replace(second=0, microsecond=0) checked_out = History.time_in_none(server_id) for c in checked_out: if c.id not in checked_out_history_ids: History.update(c.id, dt, server_id) Updates.end(update_id, status, info) except Exception as e: reset(update_id, server_id, str(e)) print(e) error = True continue except Exception as e: error = True print(e) finally: print("Read process finished.") return error
def read(license_file=None): """ entry point for reading license data from a FlexLM license server. :param license_file: manually pass in a license file in the same format the lmutil.exe displays data. :return: """ for s in license_servers: try: info = '' server_id = Server.upsert(s['hostname'], s['port']) update_id = Updates.start(server_id) check_year(server_id) checked_out_history_ids = [] if license_file: with open(license_file) as process: lines = process.read() else: process = subprocess.Popen([ lm_util, "lmstat", "-f", "-c", "{}@{}".format( s['port'], s['hostname']) ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=True) lines = process.stdout.read() has_error = parse_error_info(lines) if has_error: reset(update_id, server_id, '{}@{}: {}'.format(s['port'], s['hostname'], has_error)) raise Exception(has_error) license_data = split_license_data(lines) updates = {'update_id': update_id, 'status': None} server_information = parse_server_info(lines) if server_information: updates['status'] = server_information[2] else: updates['status'] = "DOWN" reset(update_id, server_id, '{}@{} is DOWN'.format(s['port'], s['hostname'])) raise Exception(has_error) for lic in license_data: split_line = lic.split('FLOATING LICENSE') product_id = add_product(split_line[0], server_id=server_id) users_and_workstations = add_users_and_workstations( split_line[-1]) if product_id and len(users_and_workstations): data = map_product_id(product_id, users_and_workstations) for kwargs in data: history_id = History.add(update_id=update_id, server_id=server_id, **kwargs) checked_out_history_ids.append(history_id) dt = datetime.now().replace(second=0, microsecond=0) checked_out = History.time_in_none(server_id) for c in checked_out: if c.id not in checked_out_history_ids: History.update(c.id, dt, server_id) except Exception as e: info = "{} error: {}".format(s['hostname'], str(e)) logger.error(str(e)) pass finally: logger.info('Finished reading data from \'{}\'. ' 'Update details | id:{} | status:{} | info:{}.'.format( s['hostname'], update_id, updates['status'], info)) Updates.end(update_id, updates['status'], info)