예제 #1
0
 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")
예제 #2
0
 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 ""
예제 #3
0
파일: rcPkgSunOS.py 프로젝트: sghf/opensvc
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
예제 #4
0
 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
예제 #5
0
    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")
예제 #6
0
    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")
예제 #7
0
 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'
예제 #8
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)
예제 #9
0
 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")
예제 #10
0
 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
예제 #11
0
 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)
예제 #12
0
 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
예제 #13
0
 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}}
예제 #14
0
    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
예제 #15
0
    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))
예제 #16
0
 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
예제 #17
0
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
예제 #18
0
 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
예제 #19
0
 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
예제 #20
0
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
예제 #21
0
 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)
예제 #22
0
파일: resIpLinux.py 프로젝트: sghf/opensvc
    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
예제 #23
0
파일: rcPkgLinux.py 프로젝트: sghf/opensvc
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
예제 #24
0
파일: rcPkgLinux.py 프로젝트: sghf/opensvc
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
예제 #25
0
 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
예제 #26
0
    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)
예제 #27
0
    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")
예제 #28
0
파일: rcPkgHP-UX.py 프로젝트: sghf/opensvc
def listpkg():
    if which('swlist') is None:
        return []
    lines = []
    for t in ('product', 'bundle'):
        lines += listpkg_t(t)
    return lines
예제 #29
0
파일: resFs.py 프로젝트: SLB-DeN/opensvc
 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
예제 #30
0
 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