def init(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) o = shell.call('ceph mon_status') mon_status = jsonobject.loads(o) fsid = mon_status.monmap.fsid_ existing_pools = shell.call('ceph osd lspools') for pool in cmd.pools: if pool.predefined and pool.name not in existing_pools: raise Exception( 'cannot find pool[%s] in the ceph cluster, you must create it manually' % pool.name) if pool.name not in existing_pools and (ceph.is_xsky() or ceph.is_sandstone()): raise Exception( 'The ceph storage type to be added does not support auto initialize pool, please create it manually' ) else: shell.call('ceph osd pool create %s 128' % pool.name) rsp = InitRsp() rsp.fsid = fsid self._set_capacity_to_response(rsp) return jsonobject.dumps(rsp)
def init(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) o = shell.call('ceph mon_status') mon_status = jsonobject.loads(o) fsid = mon_status.monmap.fsid_ existing_pools = shell.call('ceph osd lspools') for pool in cmd.pools: if pool.predefined and pool.name not in existing_pools: raise Exception( 'cannot find pool[%s] in the ceph cluster, you must create it manually' % pool.name) if pool.name not in existing_pools and (ceph.is_xsky() or ceph.is_sandstone()): raise Exception( 'The ceph storage type to be added does not support auto initialize pool, please create it manually' ) else: shell.call('ceph osd pool create %s 128' % pool.name) rsp = InitRsp() if cmd.nocephx is False: o = shell.call( "ceph -f json auth get-or-create client.zstack mon 'allow r' osd 'allow *' 2>/dev/null" ).strip(' \n\r\t') o = jsonobject.loads(o) rsp.userKey = o[0].key_ rsp.fsid = fsid self._set_capacity_to_response(rsp) return jsonobject.dumps(rsp)
def create(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) path = self._normalize_install_path(cmd.installPath) rsp = CreateEmptyVolumeRsp() call_string = None if ceph.is_xsky(): # do NOT round to MB call_string = 'rbd create --size %dB --image-format 2 %s' % ( cmd.size, path) rsp.size = cmd.size else: size_M = sizeunit.Byte.toMegaByte(cmd.size) + 1 call_string = 'rbd create --size %s --image-format 2 %s' % (size_M, path) rsp.size = cmd.size + sizeunit.MegaByte.toByte(1) call_string = self._wrap_shareable_cmd(cmd, call_string) skip_cmd = "rbd info %s ||" % path if cmd.skipIfExisting else "" shell.call(skip_cmd + call_string) self._set_capacity_to_response(rsp) return jsonobject.dumps(rsp)
def add_pool(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) existing_pools = shell.call('ceph osd pool ls') pool_names = existing_pools.split("\n") realname = eval('u"' + cmd.poolName + '"').encode('utf-8') if not cmd.isCreate and realname not in pool_names: raise Exception( 'cannot find the pool[%s] in the ceph cluster, you must create it manually' % realname) if cmd.isCreate and realname in pool_names: raise Exception( 'have pool named[%s] in the ceph cluster, can\'t create new pool with same name' % realname) if (ceph.is_xsky() or ceph.is_sandstone() ) and cmd.isCreate and realname not in pool_names: raise Exception( 'current ceph storage type only support add exist pool, please create it manually' ) if realname not in pool_names: shell.call('ceph osd pool create %s 128' % realname) rsp = AgentResponse() self._set_capacity_to_response(rsp) return jsonobject.dumps(rsp)
def _get_file_actual_size(self, path): ret = bash.bash_r("rbd info %s | grep -q fast-diff" % path) # if no fast-diff supported and not xsky ceph skip actual size check if ret != 0 and not ceph.is_xsky(): return None # use json format result first r, jstr = bash.bash_ro("rbd du %s --format json" % path) if r == 0 and bool(jstr): total_size = 0 result = jsonobject.loads(jstr) if result.images is not None: for item in result.images: total_size += int(item.used_size) return total_size r, size = bash.bash_ro( "rbd du %s | awk 'END {if(NF==3) {print $3} else {print $4,$5} }' | sed s/[[:space:]]//g" % path, pipe_fail=True) if r != 0: return None size = size.strip() if not size: return None return sizeunit.get_size(size)
def migrate_volume_segment(self, req): cmd = jsonobject.loads(req[http.REQUEST_BODY]) rsp = AgentResponse() src_install_path = self._normalize_install_path(cmd.srcInstallPath) dst_install_path = self._normalize_install_path(cmd.dstInstallPath) src_size = self._get_file_size(src_install_path) dst_size = self._get_dst_volume_size(dst_install_path, cmd.dstMonHostname, cmd.dstMonSshUsername, cmd.dstMonSshPassword, cmd.dstMonSshPort) if dst_size > src_size: if cmd.isXsky: # xsky / ceph -> xsky, size must be equal rsp.success = False rsp.error = "Failed to migrate volume segment because dst size: %s > src size: %s" % ( dst_size, src_size) return jsonobject.dumps(rsp) elif ceph.is_xsky() == False: # ceph -> ceph, don't check size rsp.success = True else: # xsky -> ceph, not supported rsp.success = False rsp.error = "Failed to migrate volume segment because xsky migrate to ceph is not supported now" return jsonobject.dumps(rsp) if dst_size < src_size: ret = self._resize_dst_volume(dst_install_path, src_size, cmd.dstMonHostname, cmd.dstMonSshUsername, cmd.dstMonSshPassword, cmd.dstMonSshPort) if ret != 0: rsp.success = False rsp.error = "Failed to resize volume before migrate." return jsonobject.dumps(rsp) ret = self._migrate_volume_segment( cmd.parentUuid, cmd.resourceUuid, cmd.srcInstallPath, cmd.dstInstallPath, cmd.dstMonHostname, cmd.dstMonSshUsername, cmd.dstMonSshPassword, cmd.dstMonSshPort, cmd) if ret != 0: rsp.success = False rsp.error = "Failed to migrate volume segment from one ceph primary storage to another." self._set_capacity_to_response(rsp) return jsonobject.dumps(rsp)
def _get_file_actual_size(self, path): ret = bash.bash_r("rbd info %s | grep -q fast-diff" % path) # if no fast-diff supported and not xsky ceph skip actual size check if ret != 0 and not ceph.is_xsky(): return None r, size = bash.bash_ro("rbd du %s | tail -1 | awk '{ print $3 }'" % path) if r != 0: return None if not size: return None size = size.strip('\t\n ') return sizeunit.get_size(size)
def _set_capacity_to_response(self, rsp): o = shell.call('ceph df -f json') df = jsonobject.loads(o) if df.stats.total_bytes__ is not None: total = long(df.stats.total_bytes_) elif df.stats.total_space__ is not None: total = long(df.stats.total_space__) * 1024 else: raise Exception('unknown ceph df output: %s' % o) if df.stats.total_avail_bytes__ is not None: avail = long(df.stats.total_avail_bytes_) elif df.stats.total_avail__ is not None: avail = long(df.stats.total_avail_) * 1024 else: raise Exception('unknown ceph df output: %s' % o) rsp.totalCapacity = total rsp.availableCapacity = avail if ceph.is_xsky(): rsp.type = "xsky" if not df.pools: return pools = ceph.getCephPoolsCapacity() if not pools: return rsp.poolCapacities = [] for pool in pools: poolCapacity = CephPoolCapacity(pool.poolName, pool.availableCapacity, pool.replicatedSize, pool.usedCapacity, pool.poolTotalSize) rsp.poolCapacities.append(poolCapacity)