def connect(self, req): none_shared_mount_fs_type = [ 'xfs', 'ext2', 'ext3', 'ext4', 'vfat', 'tmpfs', 'btrfs' ] cmd = jsonobject.loads(req[http.REQUEST_BODY]) if not linux.timeout_isdir(cmd.mountPoint): raise kvmagent.KvmError( '%s is not a directory, the mount point seems not setup' % cmd.mountPoint) folder_fs_type = shell.call("df -T %s|tail -1|awk '{print $2}'" % cmd.mountPoint).strip() if folder_fs_type in none_shared_mount_fs_type: raise kvmagent.KvmError( '%s filesystem is %s, which is not a shared mount point type.' % (cmd.mountPoint, folder_fs_type)) id_dir = os.path.join(cmd.mountPoint, "zstack_smp_id_file") shell.call("mkdir -p %s" % id_dir) lock_file = os.path.join(id_dir, "uuid.lock") @lock.file_lock(lock_file, locker=lock.Flock()) def check_other_smp_and_set_id_file(uuid, existUuids): o = shell.ShellCmd('''\ ls %s | grep -v %s | grep -o "[0-9a-f]\{8\}[0-9a-f]\{4\}[1-5][0-9a-f]\{3\}[89ab][0-9a-f]\{3\}[0-9a-f]\{12\}"\ ''' % (id_dir, uuid)) o(False) if o.return_code != 0: file_uuids = [] else: file_uuids = o.stdout.splitlines() for file_uuid in file_uuids: if file_uuid in existUuids: raise Exception( "the mount point [%s] has been occupied by other SMP[uuid:%s], Please attach this directly" % (cmd.mountPoint, file_uuid)) logger.debug("existing id files: %s" % file_uuids) self.id_files[uuid] = os.path.join(id_dir, uuid) if not os.path.exists(self.id_files[uuid]): # check if hosts in the same cluster mount the same path but different storages. rsp.isFirst = True for file_uuid in file_uuids: linux.rm_file_force(os.path.join(id_dir, file_uuid)) linux.touch_file(self.id_files[uuid]) linux.sync() rsp = ConnectRsp() check_other_smp_and_set_id_file(cmd.uuid, cmd.existUuids) rsp.totalCapacity, rsp.availableCapacity = self._get_disk_capacity( cmd.mountPoint) return jsonobject.dumps(rsp)
def start_prometheus_exporter(self, req): @in_bash def start_collectd(cmd): conf_path = os.path.join(os.path.dirname(cmd.binaryPath), 'collectd.conf') conf = '''Interval {{INTERVAL}} # version {{VERSION}} FQDNLookup false LoadPlugin syslog LoadPlugin aggregation LoadPlugin cpu LoadPlugin disk LoadPlugin interface LoadPlugin memory LoadPlugin network LoadPlugin virt <Plugin aggregation> <Aggregation> #Host "unspecified" Plugin "cpu" #PluginInstance "unspecified" Type "cpu" #TypeInstance "unspecified" GroupBy "Host" GroupBy "TypeInstance" CalculateNum false CalculateSum false CalculateAverage true CalculateMinimum false CalculateMaximum false CalculateStddev false </Aggregation> </Plugin> <Plugin cpu> ReportByCpu true ReportByState true ValuesPercentage true </Plugin> <Plugin disk> Disk "/^sd[a-z]$/" Disk "/^hd[a-z]$/" Disk "/^vd[a-z]$/" IgnoreSelected false </Plugin> <Plugin "interface"> {% for i in INTERFACES -%} Interface "{{i}}" {% endfor -%} IgnoreSelected false </Plugin> <Plugin memory> ValuesAbsolute true ValuesPercentage false </Plugin> <Plugin virt> Connection "qemu:///system" RefreshInterval {{INTERVAL}} HostnameFormat name PluginInstanceFormat name BlockDevice "/:hd[a-z]/" IgnoreSelected true ExtraStats "vcpu memory" </Plugin> <Plugin network> Server "localhost" "25826" </Plugin> ''' tmpt = Template(conf) conf = tmpt.render({ 'INTERVAL': cmd.interval, 'INTERFACES': interfaces, 'VERSION': cmd.version, }) need_restart_collectd = False if os.path.exists(conf_path): with open(conf_path, 'r') as fd: old_conf = fd.read() if old_conf != conf: with open(conf_path, 'w') as fd: fd.write(conf) need_restart_collectd = True else: with open(conf_path, 'w') as fd: fd.write(conf) need_restart_collectd = True cpid = linux.find_process_by_command('collectd', [conf_path]) mpid = linux.find_process_by_command('collectdmon', [conf_path]) if not cpid: bash_errorout('collectdmon -- -C %s' % conf_path) else: bash_errorout('kill -TERM %s' % cpid) if need_restart_collectd: if not mpid: bash_errorout('collectdmon -- -C %s' % conf_path) else: bash_errorout('kill -HUP %s' % mpid) else: if not mpid: bash_errorout('collectdmon -- -C %s' % conf_path) def run_in_systemd(binPath, args, log): def get_systemd_name(path): if "collectd_exporter" in path: return "collectd_exporter" elif "node_exporter" in path: return "node_exporter" elif "pushgateway" in path: return "pushgateway" def reload_and_restart_service(service_name): bash_errorout("systemctl daemon-reload && systemctl restart %s.service" % service_name) service_name = get_systemd_name(binPath) service_path = '/etc/systemd/system/%s.service' % service_name service_conf = ''' [Unit] Description=prometheus %s After=network.target [Service] ExecStart=/bin/sh -c '%s %s > %s 2>&1' ExecStop=/bin/sh -c 'pkill -TERM -f %s' Restart=always RestartSec=30s [Install] WantedBy=multi-user.target ''' % (service_name, binPath, args, '/dev/null' if log.endswith('/pushgateway.log') else log, binPath) if not os.path.exists(service_path): linux.write_file(service_path, service_conf, True) os.chmod(service_path, 0644) reload_and_restart_service(service_name) return if linux.read_file(service_path) != service_conf: linux.write_file(service_path, service_conf, True) logger.info("%s.service conf changed" % service_name) os.chmod(service_path, 0644) # restart service regardless of conf changes, for ZSTAC-23539 reload_and_restart_service(service_name) @lock.file_lock("/run/collectd-conf.lock", locker=lock.Flock()) def start_collectd_exporter(cmd): start_collectd(cmd) start_exporter(cmd) @in_bash def start_exporter(cmd): EXPORTER_PATH = cmd.binaryPath LOG_FILE = os.path.join(os.path.dirname(EXPORTER_PATH), cmd.binaryPath + '.log') ARGUMENTS = cmd.startupArguments if not ARGUMENTS: ARGUMENTS = "" os.chmod(EXPORTER_PATH, 0o755) run_in_systemd(EXPORTER_PATH, ARGUMENTS, LOG_FILE) para = jsonobject.loads(req[http.REQUEST_BODY]) rsp = kvmagent.AgentResponse() eths = bash_o("ls /sys/class/net").split() interfaces = [] for eth in eths: eth = eth.strip(' \t\n\r') if eth == 'lo': continue if eth == 'bonding_masters': continue elif eth.startswith('vnic'): continue elif eth.startswith('outer'): continue elif eth.startswith('br_'): continue elif not eth: continue else: interfaces.append(eth) for cmd in para.cmds: if "collectd_exporter" in cmd.binaryPath: start_collectd_exporter(cmd) else: start_exporter(cmd) return jsonobject.dumps(rsp)