def dockerd_exe(self): if self.dockerd_exe_init and which(self.dockerd_exe_init): return self.dockerd_exe_init elif which("dockerd"): return "dockerd" else: raise ex.excInitError("dockerd executable not found")
def _scsi_id(self, dev, args=[]): wwid = self.mpath_id(dev) if wwid is not None: return wwid if dev in self.disk_ids: return self.disk_ids[dev] if which('scsi_id'): scsi_id = 'scsi_id' elif which('/lib/udev/scsi_id'): scsi_id = '/lib/udev/scsi_id' else: return "" cmd = [scsi_id, '-g', '-u'] + args + ['-d', dev] out, err, ret = justcall(cmd) if ret == 0: id = out.split('\n')[0] if id.startswith('3') or id.startswith('2') or id.startswith('5'): id = id[1:] else: id = self.prefix_local(id) self.disk_ids[dev] = id return id sdev = dev.replace("/dev/", "/block/") cmd = [scsi_id, '-g', '-u'] + args + ['-s', sdev] out, err, ret = justcall(cmd) if ret == 0: id = out.split('\n')[0] if id.startswith('3') or id.startswith('2') or id.startswith('5'): id = id[1:] else: id = self.prefix_local(id) self.disk_ids[dev] = id return id return ""
def listpkg_ips(): """ Return a list of ips packages installed. """ # # PKGINST: SUNWzoneu # NAME: Solaris Zones (Usr) # CATEGORY: system # ARCH: i386 # VERSION: 11.11,REV=2009.04.08.17.26 # VENDOR: Sun Microsystems, Inc. # DESC: Solaris Zones Configuration and Administration # HOTLINE: Please contact your local service provider # STATUS: completely installed # if which('uname') is None: return [] cmd = ['uname', '-p'] out, _, _ = justcall(cmd) arc = out.split('\n')[0] if which('pkg') is None: return [] cmd = ['pkg', 'list', '-H'] out, _, _ = justcall(cmd) lines = [] for line in out.split('\n'): elems = line.split() if len(elems) != 3: continue data = [rcEnv.nodename, elems[0], elems[1], arc, "ips", ""] lines.append(data) return lines
def scsireserv_supported(self): if which("sg_persist") is None and which("mpathpersist") is None: self.status_log( "sg_persist or mpathpersist must be installed to use scsi-3 reservations" ) return False return True
def unprovisioner(self): try: vg = self.r.conf_get("vg") except: self.r.log.debug("skip lv unprovision: no vg option") return if not which('lvdisplay'): self.r.log.debug( "skip lv unprovision: lvdisplay command not found") return dev = self.get_dev() if dev is None: return cmd = ["lvdisplay", dev] out, err, ret = justcall(cmd) if ret != 0: self.r.log.debug("skip lv unprovision: %s is not a lv" % dev) return if not which('lvremove'): self.r.log.error("lvcreate command not found") raise ex.excError if which('wipefs') and os.path.exists(dev): self.r.vcall(["wipefs", "-a", dev]) cmd = ["lvremove", "-f", dev] ret, out, err = self.r.vcall(cmd) if ret != 0: raise ex.excError self.r.svc.node.unset_lazy("devtree")
def provisioner(self): if not which('vgdisplay'): self.r.log.error("vgdisplay command not found") raise ex.excError if not which('lvcreate'): self.r.log.error("lvcreate command not found") raise ex.excError self.size = self.r.oget("size") self.size = convert_size(self.size, _to="m") self.vg = self.r.oget("vg") cmd = ['vgdisplay', self.vg] out, err, ret = justcall(cmd) if ret != 0: self.r.log.error("volume group %s does not exist" % self.vg) raise ex.excError dev = os.path.basename(self.r.device) # create the logical volume cmd = ['lvcreate', '-n', dev, '-L', str(self.size) + 'M', self.vg] ret, out, err = self.r.vcall(cmd) if ret != 0: raise ex.excError self.r.svc.node.unset_lazy("devtree")
def _get_mem_bytes_hv(self): if which('virsh'): return self._get_mem_bytes_virsh() if which('xm'): return self._get_mem_bytes_xm() else: return '0'
def get_mcast(self): if which('netstat'): cmd = ['netstat', '-gn'] out, _, _ = justcall(cmd) return self.parse_mcast_netstat(out) elif which(rcEnv.syspaths.ip): cmd = [rcEnv.syspaths.ip, 'maddr'] out, _, _ = justcall(cmd) return self.parse_mcast_ip(out)
def docker_exe(self): """ Return the docker executable to use, using the service configuration docker_exe as the first choice, and a docker.io or docker exe found in PATH as a fallback. """ if self.docker_exe_init and which(self.docker_exe_init): return self.docker_exe_init elif which("docker.io"): return "docker.io" elif which("docker"): return "docker" else: raise ex.excInitError("docker executable not found")
def get_lv_linear(self): try: return getattr(self, "lv_linear") except AttributeError: pass self.lv_linear = {} if not which(rcEnv.syspaths.dmsetup): return self.lv_linear cmd = [rcEnv.syspaths.dmsetup, 'table', '--target', 'linear'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() if p.returncode != 0: return self.lv_linear for line in out.decode().splitlines(): l = line.split(':') if len(l) < 2: continue mapname = l[0] line = line[line.index(':') + 1:] l = line.split() if len(l) < 3: continue length = int(l[1]) * 512 / 1024 / 1024 devt = l[3] if mapname in self.lv_linear: self.lv_linear[mapname].append((devt, length)) else: self.lv_linear[mapname] = [(devt, length)] return self.lv_linear
def add_drbd_relations(self): if not which("drbdadm") or not os.path.exists('/proc/drbd'): return cmd = ["drbdadm", "dump-xml"] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() if p.returncode != 0: return from xml.etree import ElementTree as etree tree = etree.fromstring(out.decode()) for res in tree.getiterator('resource'): for host in res.findall('host'): if host.attrib['name'] != rcEnv.nodename: continue edisk = host.find('disk') edev = host.find('device') if edisk is None or edev is None: edisk = host.find('volume/disk') edev = host.find('volume/device') if edisk is None or edev is None: continue devname = 'drbd' + edev.attrib['minor'] parentpath = edisk.text d = self.get_dev_by_devpath(parentpath) if d is None: continue d.add_child(devname) c = self.get_dev(devname) c.add_parent(d.devname)
def fs_u_zfs(): if not which(rcEnv.syspaths.zfs): return [] cmd = [ rcEnv.syspaths.zfs, 'list', '-o', 'name,used,avail,mountpoint', '-H' ] (out, err, ret) = justcall(cmd) if ret != 0: return [] lines = out.split('\n') if len(lines) == 0: return [] vals = [] for line in lines: l = line.split() if len(l) != 4: continue if "@" in l[0]: # do not report clone usage continue if "osvc_sync_" in l[0]: # do not report osvc sync snapshots fs usage continue used = convert_size(l[1], _to="KB") if l[2] == '0': l[2] = '0K' avail = convert_size(l[2], _to="KB") total = used + avail pct = used / total * 100 vals.append([now, node.nodename, l[0], str(total), str(pct)]) return vals
def action(self, nodename, thr=None, **kwargs): options = self.parse_options(kwargs) timeout = options.timeout if options.timeout and options.timeout < MAX_TIMEOUT else MAX_TIMEOUT if not which("gotty"): raise HTTP(500, "The gotty executable is not installed") creds = "user:"******"private_key") cert_chain = os.path.join(rcEnv.paths.certs, "certificate_chain") cmd = [ "gotty", "--port", "0", "--random-url", "--tls", "--tls-crt", cert_chain, "--tls-key", private_key, "--timeout", str(timeout), "--once", "--ws-origin", ".*", "--permit-write", "om", options.path, "enter", "--rid", options.rid, ] env = dict(os.environ).update({ "GOTTY_CREDENTIAL": creds, }) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) thr.parent.push_proc(proc) for line in iter(proc.stderr.readline, ""): line = try_decode(line) if "https://" not in line: continue url = line.split("https://::", 1)[-1].strip() url = "https://" + creds + "@" + rcEnv.nodename + url return {"data": {"url": url}}
def zoneadm(self, action, option=None): if action in VALID_ACTIONS: cmd = [ZONEADM, "-z", self.name, action] else: self.log.error("unsupported zone action: %s", action) return 1 if option is not None: cmd += option begin = datetime.now() if os.environ.get("OSVC_ACTION_ORIGIN") == "daemon" and which("su"): # the zoneadm command gives an error when executed from osvcd. # su creates a clean execution context and makes zoneadm succeed. cmd = ["su", "root", "-c", " ".join(cmd)] self.log.info("%s", " ".join(cmd)) ret = self.lcall(cmd, env={}) duration = datetime.now() - begin if ret != 0: raise ex.excError("%s failed in %s - ret %i" % (" ".join(cmd), duration, ret)) else: self.log.info("%s done in %s - ret %i" % (" ".join(cmd), duration, ret)) self.zone_refresh() return ret
def prereq(self): s = "array#" + self.eva_name try: self.svc.node.oget(s, "type") except ex.RequiredOptNotFound: raise ex.excError("no credentials for array %s in node or cluster configuration" % self.eva_name) try: self.manager = self.svc.node.oget(s, "manager") except ex.RequiredOptNotFound: raise ex.excError("no manager set for array %s in node or cluster configuration" % self.eva_name) try: self.username = self.svc.node.oget(s, "username") except ex.RequiredOptNotFound: raise ex.excError("no username set for array %s in node or cluster configuration" % self.eva_name) try: self.password = self.svc.node.oget(s, "password") except ex.RequiredOptNotFound: raise ex.excError("no password set for array %s in node or cluster configuration" % self.eva_name) self.sssubin = self.svc.node.oget(s, "bin") if not self.sssubin: self.sssubin = which(self.sssubin) if not self.sssubin: raise ex.excError("missing sssu binary") for pair in self.pairs: if 'src' not in pair or 'dst' not in pair or 'mask' not in pair: raise ex.excError("missing parameter in pair %s"%str(pair)) ret, out, err = self.sssu(check=False) if "Error opening https connection" in out: raise ex.excError("error login to %s"%self.manager) elif "Error" in out: raise ex.excError("eva %s is not managed by %s"%(self.eva_name, self.manager))
def startip_cmd(self): if not which(rcEnv.syspaths.ipadm): raise ex.excError("crossbow ips are not supported on this system") if self.mask is None: raise ex.excError("netmask not specified nor guessable") self.wait_net_smf() ret, out, err = (0, '', '') cmd = [rcEnv.syspaths.ipadm, 'show-if', '-p', '-o', 'state', self.stacked_dev] _out, err, ret = justcall(cmd) _out = _out.strip().split("\n") if len(_out) == 0: cmd=[rcEnv.syspaths.ipadm, 'create-ip', '-t', self.stacked_dev ] r, o, e = self.vcall(cmd) cmd=[rcEnv.syspaths.ipadm, 'create-addr', '-t', '-T', 'static', '-a', self.addr+"/"+to_cidr(self.mask), self.stacked_dev+'/'+self.ipdevExt] r, o, e = self.vcall(cmd) if r != 0: cmd=[rcEnv.syspaths.ipadm, 'show-if' ] self.vcall(cmd) raise ex.excError("Interface %s is not up. ipadm cannot create-addr over it. Retrying..." % self.stacked_dev) ret += r out += o err += e if self.gateway is not None: cmd=['route', '-q', 'add', 'default', self.gateway] r, o, e = self.call(cmd, info=True, outlog=False, errlog=False) ret += r return ret, out, err
def file_to_loop(f): """Given a file path, returns the disk device associated. For example, /path/to/file => /dev/disk0s1 """ if which('hdiutil') is None: return [] if not os.path.isfile(f): return [] (ret, out, err) = call(['hdiutil', 'info', '-plist']) if ret != 0: return [] devs = [] try: pl = plistlib.readPlistFromString(out) except AttributeError as exc: raise ex.excError(str(exc)) for image in pl['images']: if image.get('image-path') == f: for se in image['system-entities']: diskdevice = se.get('dev-entry') if diskdevice is not None: devs.append(diskdevice) else: return [] return devs
def load_mpath(self): if hasattr(self, "mpath_h"): return self.mpath_h self.mpath_h = {} if which(rcEnv.syspaths.multipath): self.load_mpath_native() return self.mpath_h
def get_mp_dmp(self): self.dmp = {} if not which("vxdmpadm"): return {} cmd = ['vxdmpadm', 'getsubpaths'] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() if p.returncode != 0: return {} lines = out.split('\n') if len(lines) < 3: return {} lines = lines[2:] mp_h = {} for line in lines: l = line.split() if len(l) < 4: continue name = l[3] dev = self.devprefix + l[0] if name in self.dmp: self.dmp[name].append(dev) else: self.dmp[name] = [dev] if name not in mp_h or mp_h[name] == "unknown" or mp_h[ name] == name: d = self.vxdisk_cache.get("/dev/vx/rdmp/" + name) if d is None: wwid = name else: wwid = d.get("wwid") mp_h[name] = wwid return mp_h
def file_to_loop(f): """Given a file path, returns the loop device associated. For example, /path/to/file => /dev/loop0 """ if which('mdconfig') is None: return [] if not os.path.isfile(f): return [] (ret, out, err) = call(['mdconfig', '-l', '-v']) if ret != 0: return [] """ It's possible multiple loopdev are associated with the same file """ devs= [] for line in out.split('\n'): l = line.split() if len(l) < 4: continue path = ' '.join(l[3:]) if path != f: continue if not os.path.exists('/dev/'+l[0]): continue devs.append(l[0]) return devs
def edit(self): if self.options.key is None: self.edit_config() return buff = self.decode_key(self.options.key) if buff is None: raise ex.excError("could not decode the secret key '%s'" % self.options.key) if "EDITOR" in os.environ: editor = os.environ["EDITOR"] elif os.name == "nt": editor = "notepad" else: editor = "vi" if not which(editor): raise ex.excError("%s not found" % editor) fpath = self.tempfilename() try: with open(fpath, "wb") as f: f.write(buff) except TypeError as exc: with open(fpath, "w") as f: f.write(buff) try: os.system(' '.join((editor, fpath))) with open(fpath, "r") as f: edited = f.read() if buff == edited: return self.add_key(self.options.key, edited) finally: os.unlink(fpath)
def startip_cmd(self): if which("ifconfig") and self.alias: if ':' in self.addr: cmd = [ 'ifconfig', self.ipdev, 'inet6', 'add', '/'.join([self.addr, to_cidr(self.mask)]) ] else: cmd = [ 'ifconfig', self.stacked_dev, self.addr, 'netmask', to_dotted(self.mask), 'up' ] else: cmd = [ rcEnv.syspaths.ip, "addr", "add", '/'.join([self.addr, to_cidr(self.mask)]), "dev", self.ipdev ] ret, out, err = self.vcall(cmd) if ret != 0: return ret, out, err # ip activation may still be incomplete # wait for activation, to avoid startapp scripts to fail binding their listeners for i in range(5, 0, -1): if check_ping(self.addr, timeout=1, count=1): return ret, out, err self.log.error("timed out waiting for ip activation") raise ex.excError
def listpkg_rpm(): if not which("rpm"): return [] cmd = [ 'rpm', '-qai', '--queryformat=XX%{n} %{v}-%{r} %{arch} rpm %{installtime}\n' ] out, err, ret = justcall(cmd) lines = [] for line in out.split('\n'): if line.startswith('Signature'): sig = line.split()[-1].strip() continue elif not line.startswith('XX'): continue line = line[2:] l = line.split() if len(l) < 5: continue try: l[4] = datetime.datetime.fromtimestamp(int( l[4])).strftime("%Y-%m-%d %H:%M:%S") except: l[4] = "" x = [rcEnv.nodename] + l + [sig] lines.append(x) return lines
def listpkg_snap(): """ Example: Name Version Rev Tracking Publisher Notes core 16-2.35.4 5662 stable canonical* core inkscape 0.92.3 4274 stable inkscape* - skype 8.32.0.44 60 stable skype* classic """ if not which("snap"): return [] cmd = ["snap", "list", "--unicode=never", "--color=never"] out, err, ret = justcall(cmd) lines = [] for line in out.splitlines(): if line.startswith('Name'): header = namedtuple("header", line) continue _data = header._make(line.split()) lines.append([ rcEnv.nodename, _data.Name, "%s rev %s" % (_data.Version, _data.Rev), "", "snap", "", ]) return lines
def do_check(self): if not which('hpacucli'): return self.undef cmd = ['controller', 'all', 'show', 'status'] out, err, ret = self.hpacucli(cmd) if ret != 0: return self.undef lines = out.split('\n') if len(lines) == 0: return self.undef r = [] for line in lines: if ' Slot ' in line: l = line.split() idx = l.index('Slot') uslot = l[idx + 1] slot = 'slot ' + uslot _r = [] _r += self.check_controller(uslot) _r += self.check_array(uslot) _r += self.check_logicaldrive(uslot) _r += self.check_physicaldrive(uslot) for inst, value in _r: r.append({ "instance": ".".join((slot, inst)), "value": str(value), "path": '', }) return r
def load_lv(self, lv): if not which("lvdisplay"): return cmd = ["lvdisplay", "-v", lv] p = Popen(cmd, stdout=PIPE, stderr=PIPE) out, err = p.communicate() if p.returncode: return vgname = lv.split('/')[2] # parser h = {} for line in out.split('\n'): line = line.strip() if 'LV Size' in line: size = int(line.split()[-1]) if not line.startswith('/dev'): continue pv, le, pe = line.split() h[pv] = int(pe) * self.pe_size[vgname] # use the linux lvm naming convention devname = lv.replace('/dev/','').replace('-','--').replace('/','-') d = self.add_dev(devname, size, "linear") for pv in h: d.add_parent(pv.replace('/dev/disk/', ''), size=h[pv]) d.set_devpath(lv) parent_dev = self.get_dev_by_devpath(pv) if parent_dev is None: continue parent_dev.add_child(d.devname)
def provisioner(self): if not which('vxassist'): raise ex.excError("vxassist command not found") if self.r.has_it(): self.r.log.info("skip vxvol provision: %s already exists" % self.r.fullname) return try: self.size = self.r.conf_get("size") self.size = str(self.size).upper() size_parm = [str(convert_size(self.size, _to="m")) + 'M'] except Exception as e: self.r.log.info("skip vxvol provisioning: %s %s" % (self.r.fullname, str(e))) return create_options = self.r.oget("create_options") # strip dev dir in case the alloc vxassist parameter was formatted using sub_devs # lazy references for idx, option in enumerate(create_options): create_options[idx] = option.replace("/dev/vx/dsk/", "") # create the logical volume cmd = ['vxassist', '-g', self.r.vg, "make", self.r.name ] + size_parm + create_options ret, out, err = self.r.vcall(cmd) if ret != 0: raise ex.excError(err) self.r.can_rollback = True self.r.svc.node.unset_lazy("devtree")
def listpkg(): if which('swlist') is None: return [] lines = [] for t in ('product', 'bundle'): lines += listpkg_t(t) return lines
def fsck(self): if self.fs_type in ("", "tmpfs", "shm", "shmfs", "none") or os.path.isdir(self.device): # bind mounts are in this case return self.set_fsck_h() if self.fs_type not in self.fsck_h: self.log.debug("no fsck method for %s" % self.fs_type) return bin = self.fsck_h[self.fs_type]['bin'] if which(bin) is None: self.log.warning("%s not found. bypass." % self.fs_type) return if 'reportcmd' in self.fsck_h[self.fs_type]: cmd = self.fsck_h[self.fs_type]['reportcmd'] (ret, out, err) = self.vcall(cmd, err_to_info=True) if ret not in self.fsck_h[self.fs_type]['reportclean']: return cmd = self.fsck_h[self.fs_type]['cmd'] (ret, out, err) = self.vcall(cmd) if 'allowed_ret' in self.fsck_h[self.fs_type]: allowed_ret = self.fsck_h[self.fs_type]['allowed_ret'] else: allowed_ret = [0] if ret not in allowed_ret: raise ex.excError
def stopip_cmd(self): if not which(rcEnv.syspaths.ipadm): raise ex.excError("crossbow ips are not supported on this system") ret, out, err = (0, '', '') if self.gateway is not None: cmd=['route', '-q', 'delete', 'default', self.gateway] r, o, e = self.call(cmd, info=True, outlog=False, errlog=False) ret += r cmd=[rcEnv.syspaths.ipadm, 'delete-addr', self.stacked_dev+'/'+self.ipdevExt] r, o, e = self.vcall(cmd) ret += r out += o err += e cmd = [rcEnv.syspaths.ipadm, 'show-addr', '-p', '-o', 'state', self.stacked_dev ] _out, _, _ = justcall(cmd) _out = _out.strip().split("\n") if len(_out) > 0: self.log.info("skip delete-ip because addrs still use the ip") return ret, out, err cmd=[rcEnv.syspaths.ipadm, 'delete-ip', self.stacked_dev] r, o, e = self.vcall(cmd) ret += r out += o err += e return ret, out, err