def create_lun(self, volume_name, volume_size, sparse=False, block_size=None): """create_volume. POST .../volumes :param volume_name: :param volume_size: :return: """ volume_size_str = str(volume_size) jbody = { 'name': volume_name, 'size': volume_size_str, 'sparse': sparse } if block_size: jbody['blocksize'] = block_size req = '/volumes' LOG.debug("create volume %s", str(jbody)) resp = self.rproxy.pool_request('POST', req, json_data=jbody) if not resp["error"] and resp["code"] in (200, 201): return if resp["error"] is not None: if resp["error"]["errno"] == str(5): msg = _('Failed to create volume %s.' % resp['error']['message']) raise jexc.JDSSRESTException(msg) raise jexc.JDSSRESTException('Failed to create volume.')
def modify_property_lun(self, volume_name, prop=None): """Change volume properties :prop: volume_name: volume name :prop: prop: dictionary of volume properties in format { "property_name": "<name of property>", "property_value":"<value of a property>"} """ req = '/volumes/%s/properties' % volume_name resp = self.rproxy.pool_request('PUT', req, json_data=prop) if resp["code"] in (200, 201, 204): LOG.debug( "volume %s properties updated", volume_name) return if resp["code"] == 500: if resp["error"] is not None: if resp["error"]["errno"] == 1: raise jexc.JDSSResourceNotFoundException( res=volume_name) raise jexc.JDSSRESTException(request=req, reason=resp['error']['message']) raise jexc.JDSSRESTException(request=req, reason="unknown")
def create_volume_from_snapshot(self, volume_name, snapshot_name, original_vol_name, **options): """create_volume_from_snapshot. POST /volumes/<string:volumename>/clone :param volume_name: volume that is going to be created :param snapshot_name: slice of original volume :param original_vol_name: sample copy :return: """ req = '/volumes/' + original_vol_name + '/clone' jbody = { 'name': volume_name, 'snapshot': snapshot_name, 'sparse': False } if 'sparse' in options: jbody['sparse'] = options['sparse'] LOG.debug("create volume %(vol)s from snapshot %(snap)s", { 'vol': volume_name, 'snap': snapshot_name }) resp = self.rproxy.pool_request('POST', req, json_data=jbody) if not resp["error"] and resp["code"] in (200, 201, 204): return if resp["code"] == 500: if resp["error"]: if resp["error"]["errno"] == 100: raise jexc.JDSSVolumeExistsException(volume=volume_name) args = {"vol": volume_name, "e": resp['error']['message']} msg = _('Failed to create volume %(vol)s, err: %(e)s') % args raise jexc.JDSSRESTException(msg) raise jexc.JDSSRESTException('unable to create volume')
def delete_lun(self, volume_name, recursively_children=False, recursively_dependents=False, force_umount=False): """delete_volume. DELETE /volumes/<string:volumename> :param volume_name: :return: """ jbody = {} if recursively_children: jbody['recursively_children'] = True if recursively_dependents: jbody['recursively_dependents'] = True if force_umount: jbody['force_umount'] = True req = '/volumes/' + volume_name LOG.debug(("delete volume:%(vol)s " "recursively children:%(args)s"), {'vol': volume_name, 'args': jbody}) if len(jbody) > 0: resp = self.rproxy.pool_request('DELETE', req, json_data=jbody) else: resp = self.rproxy.pool_request('DELETE', req) if resp["code"] == 204: LOG.debug( "volume %s deleted", volume_name) return # Handle DNE case if resp["code"] == 500: if 'message' in resp['error']: if self.resource_dne_msg.match(resp['error']['message']): LOG.debug("volume %s do not exists, delition success", volume_name) return # Handle volume busy if resp["code"] == 500 and resp["error"]: if resp["error"]["errno"] == 1000: LOG.warning( "volume %s is busy", volume_name) raise exception.VolumeIsBusy(volume_name=volume_name) raise jexc.JDSSRESTException('Failed to delete volume.')
def extend_lun(self, volume_name, volume_size): """create_volume. PUT /volumes/<string:volume_name> """ req = '/volumes/' + volume_name volume_size_str = str(volume_size) jbody = {'size': volume_size_str} LOG.debug("jdss extend volume %(volume)s to %(size)s", { "volume": volume_name, "size": volume_size_str }) resp = self.rproxy.pool_request('PUT', req, json_data=jbody) if not resp["error"] and resp["code"] == 201: return if resp["error"]: raise jexc.JDSSRESTException('Failed to extend volume {}'.format( resp['error']['message'])) raise jexc.JDSSRESTException('Failed to extend volume.')
def get_iface_info(self): """get_iface_info GET /network/interfaces :return list of internet ifaces """ req = '/network/interfaces' LOG.debug("get network interfaces") resp = self.rproxy.request('GET', req) if (resp['error'] is None) and (resp['code'] == 200): return resp['data'] raise jexc.JDSSRESTException(resp['error']['message'])
def get_luns(self): """get_all_pool_volumes. GET /pools/<string:poolname>/volumes :param pool_name :return list of all pool volumes """ req = '/volumes' LOG.debug("get all volumes") resp = self.rproxy.pool_request('GET', req) if resp['error'] is None and resp['code'] == 200: return resp['data'] raise jexc.JDSSRESTException(resp['error']['message'])
def get_jdss_exceptions(): out = [ jexc.JDSSException(reason="Testing"), jexc.JDSSRESTException(request="ra request", reason="Testing"), jexc.JDSSRESTProxyException(host="test_host", reason="Testing"), jexc.JDSSResourceNotFoundException(res="test_resource"), jexc.JDSSVolumeNotFoundException(volume="test_volume"), jexc.JDSSSnapshotNotFoundException(snapshot="test_snapshot"), jexc.JDSSResourceExistsException(res="test_resource"), jexc.JDSSSnapshotExistsException(snapshot="test_snapshot"), jexc.JDSSVolumeExistsException(volume="test_volume"), jexc.JDSSSnapshotIsBusyException(snapshot="test_snapshot") ] return out
def get_snapshots(self, volume_name): """get_snapshots. GET /volumes/<string:volumename>/ snapshots :param volume_name: that snapshot belongs to :return: { "data": [ { "referenced": "65536", "name": "MySnapshot", "defer_destroy": "off", "userrefs": "0", "primarycache": "all", "type": "snapshot", "creation": "2015-5-27 16:8:35", "refcompressratio": "1.00x", "compressratio": "1.00x", "written": "65536", "used": "0", "clones": "", "mlslabel": "none", "secondarycache": "all" } ], "error": null } """ req = '/volumes/' + volume_name + '/snapshots' LOG.debug("get snapshots for volume %s ", volume_name) resp = self.rproxy.pool_request('GET', req) if not resp["error"] and resp["code"] == 200: return resp["data"]["entries"] if resp['code'] == 500: if 'message' in resp['error']: if self.resource_dne_msg.match(resp['error']['message']): raise jexc.JDSSResourceNotFoundException(volume_name) raise jexc.JDSSRESTException('unable to get snapshots')
def test_remove_target_volume_fail_to_delete(self): jdssd, ctx = self.get_driver(CONFIG_OK) vol = fake_volume.fake_volume_obj(ctx) vol.id = UUID_1 target_name = CONFIG_OK['target_prefix'] + UUID_1 jdssd.ra.detach_target_vol.return_value = None jdssd.ra.delete_target.side_effect = (jexc.JDSSRESTException( reason='running test', request='test')) self.assertRaises(exception.VolumeBackendAPIException, jdssd._remove_target_volume, vol) jdssd.ra.detach_target_vol.assert_called_once_with( target_name, jcom.vname(UUID_1)) jdssd.ra.delete_target.assert_called_with(target_name)
def get_pool_stats(self): """get_pool_stats. GET /pools/<string:poolname> :param pool_name: :return: { "data": { "available": "24433164288", "status": 24, "name": "Pool-0", "scan": { "errors": 0, "repaired": "0", "start_time": 1463476815, "state": "finished", "end_time": 1463476820, "type": "scrub" }, "iostats": { "read": "0", "write": "0", "chksum": "0" }, "vdevs": [ { "name": "scsi-SSCST_BIOoWKF6TM0qafySQBUd1bb392e", "iostats": { "read": "0", "write": "0", "chksum": "0" }, "disks": [ { "led": "off", "name": "sdb", "iostats": { "read": "0", "write": "0", "chksum": "0" }, "health": "ONLINE", "sn": "d1bb392e", "path": "pci-0000:04:00.0-scsi-0:0:0:0", "model": "oWKF6TM0qafySQBU", "id": "scsi-SSCST_BIOoWKF6TM0qafySQBUd1bb392e", "size": 30064771072 } ], "health": "ONLINE", "vdev_replacings": [], "vdev_spares": [], "type": "" } ], "health": "ONLINE", "operation": "none", "id": "11612982948930769833", "size": "29796335616" }, "error": null } """ req = "" LOG.debug("Get pool %s fsprops", self.pool) resp = self.rproxy.pool_request('GET', req) if not resp["error"] and resp["code"] == 200: return resp["data"] raise jexc.JDSSRESTException('Unable to get pool info')
def delete_snapshot(self, volume_name, snapshot_name, recursively_children=False, recursively_dependents=False, force_umount=False): """delete_snapshot. DELETE /volumes/<string:volumename>/snapshots/ <string:snapshotname> :param volume_name: volume that snapshot belongs to :param snapshot_name: snapshot name :param recursively_children: boolean indicating if zfs should recursively destroy all children of resource, in case of snapshot remove all snapshots in descendant file system (default false). :param recursively_dependents: boolean indicating if zfs should recursively destroy all dependents, including cloned file systems outside the target hierarchy (default false). :param force_umount: boolean indicating if volume should be forced to umount (defualt false). :return: """ if not self.is_snapshot(volume_name, snapshot_name): return req = '/volumes/' + volume_name + '/snapshots/' + snapshot_name LOG.debug("delete snapshot %(snap)s of volume %(vol)s", { 'snap': snapshot_name, 'vol': volume_name }) jbody = {} if recursively_children: jbody['recursively_children'] = True if recursively_dependents: jbody['recursively_dependents'] = True if force_umount: jbody['force_umount'] = True resp = dict() if len(jbody) > 0: resp = self.rproxy.pool_request('DELETE', req, json_data=jbody) else: resp = self.rproxy.pool_request('DELETE', req) if resp["code"] in (200, 201, 204): LOG.debug("snapshot %s deleted", snapshot_name) return if resp["code"] == 500: if resp["error"]: if resp["error"]["errno"] == 1000: raise jexc.JDSSSnapshotIsBusyException( snapshot=snapshot_name) msg = 'Failed to delete snapshot {}, err: {}'.format( snapshot_name, resp['error']['message']) raise jexc.JDSSRESTException(msg) msg = 'Failed to delete snapshot {}'.format(snapshot_name) raise jexc.JDSSRESTException(msg)