def set_chat_id(email, tgname, chat_id): try: profile = None log.info( f"set chat id email: {email} tgname: {tgname} chat_id: {chat_id}") # find profile if email: # do not use tgname in this search! profile = Profile.objects.get(user__email=email) else: if tgname: # case-insensitive search for telegram_name profile = Profile.objects.get(telegram_name__iexact=tgname) else: profile = Profile.objects.get(telegram_name=str(chat_id)) log.info(f"got profile: {profile}") # verify profile if profile.telegram_name.lower() != tgname.lower( ) and profile.telegram_name != str(chat_id): if tgname: return 'Set telegram name {} in profile'.format(tgname) else: return 'Set telegram name {} in profile'.format(chat_id) rs = RemoteServer(ci=profile.ci) if tgname: jr = rs.api_admin_tglink(email, tgname, chat_id) else: jr = rs.api_admin_tglink(email, chat_id, chat_id) r = json.loads(jr) # sync if needed if rs.ci != myci(): for username in r['sync']: data = rs.get_user(username) ie = Impex() ie.set_verbosity(0) ie.preimport_cleanup(data) ie.import_data(data) return r['msg'] except Profile.DoesNotExist as e: log.info('Not found profile for tg user {}. Try little later?'.format( tgname)) if tgname: return "Telegram user with name '{}' not known in Okerr. Sorry. Please set this name in okerr profile first and try little later.".format( tgname) else: return "Telegram user with id {} not known in Okerr. Sorry. Please set this id in okerr profile first and try little later.".format( chat_id) except Profile.MultipleObjectsReturned as e: log.error('Multiple profiles for tg user {}'.format(tgname)) return "More then one telegram user '{}' in Okerr. Use /on <email> command.".format( tgname)
def UNUSED_handle_sync(url, overwrite, verbosity): ci = myci() rurl = urllib.parse.urljoin(url,'/api/admin/cilist') r = requests.get(rurl) if r.status_code == 200: userlist = r.text.split('\n') else: raise Exception('Error code: {} from url {}'.format(r.status_code, rurl)) for email in userlist: if not email: continue try: luser = User.objects.get(email=email) profile = luser.profile if profile.ci == ci and not overwrite: raise Exception('user: {} ci: {} is mine and not overwrite!'.format(email, ci)) except User.DoesNotExist: pass except Profile.DoesNotExist: # no profile. okay. we will re-create it. it's safe - we dont have profile anyway pass data = get_content(url = url, email = email) #overwrite always True here, because we always overwrite other-ci and check for local-ci above handle_import(data, True, verbosity)
def add_arguments(self,parser): read_group = parser.add_argument_group('Read') read_group.add_argument('--list', action='store_true', help='list all profiles') read_group.add_argument('--info', action='store_true', help='brief summary info') read_group.add_argument('--cilist', metavar='ci', type=int, nargs='?', default=None, const=myci(), help='list profiles for this ci (default, my: {})'.format(myci())) read_group.add_argument('--cluster', default=False, action='store_true', help='list cluster users') read_group.add_argument('--hostinfo', metavar='host', nargs='?', const='*',default=None, help='hostinfo') read_group.add_argument('--compare', default=False, action='store_true', help='compare users on all machines in cluster') manage_group = parser.add_argument_group('Manage') manage_group.add_argument('--export', default=False, action='store_true', help='export profile for --user') manage_group.add_argument('--import', action='store_true', default=False, help='load one profile from (--file) OR (--url and --user)') manage_group.add_argument('--sync', metavar='MACHINE_URL', default=None, help='sync with remote url, e.g https://alpha.okerr.com/') manage_group.add_argument('--syncmap', action='store_true', default=False, help='sync according to map') manage_group.add_argument('--setci', type=int, metavar='CI', default=None, const=myci(), nargs='?', help='set ci for --user') manage_group.add_argument('--takeci', type=int, metavar='CI', default=None, help='set my ci for all users with this ci') manage_group.add_argument('--reanimate', default=False, action='store_true', help='reanimate everything for --user or all local') wipe_group = parser.add_argument_group('Delete') wipe_group.add_argument('--ciwipe', metavar='ci', type=int, nargs='?', default = None, const=False, help='drop profiles for other ci') wipe_group.add_argument('--otherciwipe', default=False, action='store_true', help='drop profiles for all other ci') wipe_group.add_argument('--wipe', default = False, action='store_true', help='Wipe one user') opts_group = parser.add_argument_group('Options') # opts_group.add_argument('--batch', '-b', action='store_true', help='batch mode (show briefly)') opts_group.add_argument('--user', default=None, help='user email') opts_group.add_argument('-f','--file', metavar='FILENAME', default=None, help='work with this file') opts_group.add_argument('--url', metavar='URL', default=None, help='work with this URL. e.g. https://alpha.okerr.com/') opts_group.add_argument('--overwrite',action='store_true', default=False, help='delete old profile when importing') opts_group.add_argument('--dblog',action='store_true', default=False, help='log db queries') opts_group.add_argument('--remote', default=False, action='store_true', help='do remote operations if needed') opts_group.add_argument('--clone', default=False, action='store_true', help='modify imported data for cloning (e.g. set unused textids)') opts_group.add_argument('--skip', nargs='*', default=list(), help='modify imported data for cloning (e.g. set unused textids)')
def sync(self, url, overwrite=True): rs = RemoteServer(url = url) User = get_user_model() Profile = self.get_model('Profile') ci = myci() rci = rs.get_ci() userlist = rs.get_userlist() for email in userlist: if not email: continue log.info('sync user {} from {} rci: {}'.format(email, url2host(url), rci)) self.vprint(2, 'sync user {} from {}'.format(email, url2host(url))) profile = None # get local user try: profile = Profile.objects.get(user__email=email) if profile.ci == ci and not overwrite: log.error('sync: user {} ci: {} is mine!!'.format(email, ci)) raise Exception('user: {} ci: {} is mine and not overwrite!'.format(email, ci)) except User.DoesNotExist: pass except Profile.DoesNotExist: # no profile. okay. we will re-create it. it's safe - we dont have profile anyway pass try: data = rs.get_user(email) except (requests.exceptions.RequestException, RemoteServerExc) as e: log.warning('sync error (user {} from {}): {}'.format(email, rs.name, str(e))) continue # delete this user before importing if profile: if overwrite: # log.debug("ZZZ luser.delete (profile: {})".format(profile)) profile.predelete() profile.delete() else: # do not import this user, because it's local and not overwrite continue #log.debug("ZZZ import data") self.import_data(data) self.delete_deleted(rs)
def cmd_debug(update, ctx): bot = ctx.bot args = ctx.args reg_command(update, ctx) chat_id = update.message.chat_id tgname = update.message.from_user.username log.info('debug @{} #{}'.format(tgname, chat_id)) bot.send_message(chat_id=update.message.chat_id, text="You are @{}, chat_id: {}".format(tgname, chat_id)) for p in Profile.objects.filter(telegram_name=tgname): bot.send_message(chat_id=update.message.chat_id, text="Profile {} @{}, chat_id: {} ci: {}/{}".format( p.user.username, p.telegram_name, p.telegram_chat_id, p.ci, myci()))
def cron(cls): modelcrontime = 1800 # 30min modelcrontime_big = 86400 # 2 if cls.lastcron and int(time.time()) < cls.lastcron+modelcrontime: # print "skip cronjob ({} < {} + {}, will run in {} seconds)".\ # format(int(time.time()),cls.lastcron,modelcrontime,cls.lastcron+modelcrontime-int(time.time())) return cls.lastcron=int(time.time()) cls.syncmap() if int(time.time()) > cls.lastcron_big+modelcrontime_big: if hasattr(settings,'IMPORT_PROFILE') and settings.IMPORT_PROFILE: User = get_user_model() filename = os.path.join(settings.BASE_DIR, settings.IMPORT_PATH, settings.IMPORT_PROFILE) with open(filename, "r") as infile: data = json.load(infile) if data['ci'] == myci(): # only if we should use this user try: user = User.objects.get(email=data['email']) # delete user if exist if user.profile: print(user.profile) user.profile.predelete() user.profile.delete() else: # user.delete() pass except User.DoesNotExist: # no such user, great! pass ie = Impex() ie.set_verbosity(0) ie.import_data(data) log.info("cron reimported user {}".format(data['email'])) else: # print("not our ci") pass cls.lastcron_big = int(time.time())
def lock(pid, numi=50): """ lock numi records. we lock by setting lockpid to non-null (random) value. we cannot set to PID npname - netprocess name """ now = timezone.now() remote = True # hostname = 'charlie' # hostname = settings.HOSTNAME my_ci = myci() # nested_q=Indicator.objects.filter(lockpid__isnull=True, ci=my_ci, problem=False, disabled=False, dead=False, deleted_at__isnull=True, scheduled__lte=now, cm__remote=remote).exclude(last_fail_machine=machine).values_list('pk', flat=True)[:numi] nested_q = Indicator.objects.filter( lockpid__isnull=True, ci=my_ci, problem=False, disabled=False, dead=False, deleted_at__isnull=True, scheduled__lte=now, cm__remote=remote).order_by('scheduled').values_list('pk', flat=True)[:numi] nlocked = Indicator.objects.filter(pk__in=list(nested_q), lockpid__isnull=True, ci=my_ci, disabled=False, deleted_at__isnull=True, scheduled__lte=now, cm__remote=remote).update(lockpid=pid, lockat=now) return nlocked
def handle(self, *args, **options): #print "options:",options user = None profile = None if options['verbosity'] >= 1: log = logging.getLogger('okerr') log.setLevel(logging.DEBUG) log.addHandler(logging.StreamHandler()) # prepare data try: if options['user'] and not options['clone']: email = options['user'] user = User.objects.get(email=options['user']) profile = user.profile except User.DoesNotExist: print("No such user") except Profile.DoesNotExist: print("No such profile") if options['dblog']: l = logging.getLogger('django.db.backends') l.setLevel(logging.DEBUG) l.addHandler(logging.StreamHandler()) if options['skip']: for s in options['skip']: RemoteServer.skip(s) if options['hostinfo']: if options['hostinfo'] == 'all': rs = RemoteServer.me() for rrs in rs.all_rs(): print("== Hostinfo for %s" % rrs) print(rrs.hostinfo()) else: rs = RemoteServer(name = options['hostinfo']) print(rs.hostinfo()) return if options['cluster']: print(json.dumps(settings.MACHINES, indent=4)) return if options['compare']: ul = dict() users = list() badusers = list() me = RemoteServer.me() for rs in me.all_rs(): ul[rs.name] = rs.list() for ulist in list(ul.values()): for u in ulist: email = u['user'] if not email in users: users.append(email) mnames = sorted(ul.keys()) fmt = "{:<50}|{:1}| " + "{:<15}| " * (len(mnames)) titles = list() for m in mnames: rs = RemoteServer(name = m) print(rs, rs.ci) titles.append("{} ({})".format(rs.name, rs.ci)) print(fmt.format('EMAIL','X', *titles)) print(fmt.format('-'*50,'-',*["-"*15 for x in range(len(mnames))])) for username in users: cil = list() for m in mnames: urec = [urec for urec in ul[m] if urec['user'] == username] if urec: cil.append(urec[0]['ci']) else: cil.append('-') if cil[1:] == cil[:-1]: cil.insert(0,'') if options['verbosity']>=1: print(fmt.format(username, *cil)) else: cil.insert(0,'X') print(fmt.format(username, *cil)) return if options['reanimate']: if profile: print("single reanimate", profile) profile.reanimate() else: for p in Profile.objects.filter(ci = myci()): print("reanimate",p) p.reanimate() return if options['info']: print("Host: {} Cluster: {} ci: {}".format(repr(settings.HOSTNAME), repr(settings.CLUSTER_NAME), myci())) print("Profiles: {} / {}".format(Profile.objects.filter(ci=myci()).count(), Profile.objects.count())) return if options['list']: for p in Profile.objects.all(): print(p.ci, p.user.username) elif options['cilist'] is not None: for p in Profile.objects.filter(ci=options['cilist']).all(): print(p.user.username) elif options['wipe']: if not (user or profile): print("need either user ({}) or profile ({})".format(user, profile)) if user: user.delete() if profile: profile.delete() print("deleted") elif options['ciwipe'] is not None: if options['ciwipe'] == myci(): print("cannot ciwipe for my own ci {}".format(myci())) return for p in Profile.objects.filter(ci=options['ciwipe']).all(): if options['verbosity']>=1: print("delete {} ci: {}".format(p, p.ci)) p.user.delete() p.delete() elif options['otherciwipe']: ci = myci() for p in Profile.objects.all(): if p.ci == ci: if options['verbosity']>=1: print("skip profile {} ci: {}".format(p, p.ci)) else: if options['verbosity']>=1: print("delete {} ci: {}".format(p, p.ci)) p.user.delete() p.delete() elif options['export']: if profile: handle_export(profile, options['file'], options['verbosity']) else: print("Need --user") elif options['import']: data = get_content(filename = options['file'], url = options['url'], email = options['user']) if options['clone']: data = clone(data, options['user']) handle_import(data, options['overwrite'], options['verbosity']) elif options['sync']: handle_sync(options['sync'], options['overwrite'], options['verbosity']) elif options['syncmap']: ie = Impex() ie.set_verbosity(options['verbosity']) ie.syncmap() return elif options['takeci'] is not None: for profile in Profile.objects.filter(ci=options['takeci']): print("process profile", profile) ## profile = Profile.objects.get(user__email = options['user']) setci_local(profile, myci()) if options['remote']: setci_remote(profile.user.username, myci()) else: print("skip remote, because no --remote") return elif options['setci'] is not None: if options['user']: profile = Profile.objects.get(user__email = options['user']) setci_local(profile, options['setci']) if options['remote']: setci_remote(options['user'], options['setci']) else: print("skip remote, because no --remote") else: print("need --user") return print("setci {} for user {}".format(options['setci'], email)) # change for profile and projects ci = options['setci'] profile.set_ci(options['setci']) profile.save() else: print("Whaat?")