def install(self, cfgfile, postrun, timeout, **kwargs): """create database intance""" if not os.path.exists(cfgfile): raise ValueError('Config file not exist') args = [SH, MYSQLINSTALL, '--defaults-file=%s' % cfgfile] args.extend(self.base_opts) replication = kwargs.pop('replication', None) auth = kwargs.pop('auth') logfile = kwargs.get('logfile') if not systemutils.POSIX: # just for test on windows LOG.info('will call %s', ' '.join(args)) else: with goperation.tlock('gopdb-install', 30): pid = safe_fork() if pid == 0: os.closerange(3, systemutils.MAXFD) logfile = logfile or os.devnull with open(logfile, 'wb') as f: os.dup2(f.fileno(), 1) os.dup2(f.fileno(), 2) try: os.execv(SH, args) except OSError: os._exit(1) else: try: wait(pid, timeout) except: raise finally: LOG.info('%s has been exit' % MYSQLINSTALL) eventlet.sleep(0) self.start(cfgfile) eventlet.sleep(3) binlog = self._init_passwd(cfgfile, auth, replication) if postrun: postrun(binlog)
def map_resources(resource_ids): # 删除过期缓存 CDNRESOURCE.expire() need = set(resource_ids) provides = set(CDNRESOURCE.keys()) notmiss = need & provides # 有资源在进程缓存字典中 if notmiss: caches_time_dict = {} # 本地最旧缓存时间点 time_point = int(time.time()) for resource_id in notmiss: # 获取单个资源本地缓存时间点 cache_on = int(CDNRESOURCE.expiretime(resource_id)) - cdncommon.CACHETIME if cache_on < time_point: time_point = cache_on caches_time_dict[resource_id] = cache_on cache = get_cache() scores = cache.zrangebyscore(name=cdncommon.CACHESETNAME, min=str(time_point - 3), max='+inf', withscores=True, score_cast_func=int) if scores: for data in scores: resource_id = int(data[0]) cache_on = int(data[1]) # redis中缓存时间点超过本地缓存时间点 # 弹出本地缓存 try: # 保险做法本地缓存时间回退3秒 if cache_on > caches_time_dict[resource_id] - 3: CDNRESOURCE.pop(resource_id, None) except KeyError: continue caches_time_dict.clear() # 没有本地缓存的资源数量 missed = need - set(CDNRESOURCE.keys()) if missed: # 重新从数据库读取 with goperation.tlock('gogamechen1-cdnresource'): resources = cdnresource_controller.list(resource_ids=missed, versions=True, domains=True, metadatas=True) for resource in resources: resource_id = resource.get('resource_id') agent_id = resource.get('agent_id') port = resource.get('port') internal = resource.get('internal') name = resource.get('name') etype = resource.get('etype') domains = resource.get('domains') versions = resource.get('versions') metadata = resource.get('metadata') if internal: if not metadata: raise ValueError('Agent %d not online, get domain entity fail' % agent_id) hostnames = [metadata.get('local_ip')] else: if not domains: if not metadata: raise ValueError('Agent %d not online get domain entity fail' % agent_id) if metadata.get('external_ips'): hostnames = metadata.get('external_ips') else: hostnames = [metadata.get('local_ip')] else: hostnames = domains schema = 'http' if port == 443: schema = 'https' netlocs = [] for host in hostnames: if port in (80, 443): netloc = '%s://%s' % (schema, host) else: netloc = '%s://%s:%d' % (schema, host, port) netlocs.append(netloc) CDNRESOURCE.setdefault(resource_id, dict(name=name, etype=etype, agent_id=agent_id, internal=internal, versions=versions, netlocs=netlocs, port=port, domains=domains))
def upload(self, user, group, ipaddr, port, rootpath, fileinfo, logfile, timeout): jsonutils.schema_validate(fileinfo, FILEINFOSCHEMA) if timeout: timeout = int(timeout) if timeout > 7200: raise ValueError('Timeout over 7200 seconds') with goperation.tlock(self.executer): logfile = logfile or os.devnull executable = systemutils.find_executable(self.executer) token = str(uuidutils.generate_uuid()).replace('-', '') args = [ executable, '--home', rootpath, '--token', token, '--port', str(port) ] ext = fileinfo.get('ext') or os.path.splitext( fileinfo.get('filename'))[1][1:] if ext.startswith('.'): ext = ext[1:] if not ext: raise exceptions.PreWebSocketError('ext is empty') filename = '%s.%s' % (fileinfo.get('md5'), ext) self.output = os.path.join(rootpath, filename) # 判断文件是否存在 if os.path.exists(self.output): raise exceptions.PreWebSocketError('file exist with same name') self.size = fileinfo.get('size') # 准备文件目录 path = os.path.dirname(self.output) if not os.path.exists(path): os.makedirs(path, mode=0o775) if user or group: os.chown(path, user, group) else: if not os.path.isdir(path): raise exceptions.PreWebSocketError( 'prefix path is not dir') if not ext or ext == 'tmp': raise exceptions.PreWebSocketError( 'Can not find file ext or ext is tmp') # 临时文件名 self.tmp = os.path.join( rootpath, '%s.tmp' % str(uuidutils.generate_uuid()).replace('-', '')) args.extend(['--outfile', self.tmp]) args.extend(['--md5', fileinfo.get('md5')]) args.extend(['--size', str(fileinfo.get('size'))]) args.extend(['--log-file', logfile]) args.extend(['--loglevel', 'info']) changeuser = functools.partial(systemutils.drop_privileges, user, group) with open(os.devnull, 'wb') as f: LOG.debug('Websocket command %s %s' % (executable, ' '.join(args))) if systemutils.WINDOWS: sub = subprocess.Popen(executable=executable, args=args, stdout=f.fileno(), stderr=f.fileno(), close_fds=True, preexec_fn=changeuser) pid = sub.pid else: pid = safe_fork(user=user, group=group) if pid == 0: os.dup2(f.fileno(), sys.stdout.fileno()) os.dup2(f.fileno(), sys.stderr.fileno()) os.closerange(3, systemutils.MAXFD) try: os.execv(executable, args) except OSError: os._exit(1) LOG.info('Websocket recver start with pid %d' % pid) def _kill(): try: p = psutil.Process(pid=pid) name = p.name() except psutil.NoSuchProcess: return if name == self.executer: LOG.warning('Websocket recver overtime, kill it') p.kill() self.pid = pid hub = hubs.get_hub() self.timer = hub.schedule_call_global(timeout or 3600, _kill) return dict(port=port, token=token, ipaddr=ipaddr, filename=filename)