def rollback_volume_to_snapshot(self, volume_name, snapshot_name): """Rollback volume to its snapshot POST /volumes/<volume_name>/snapshots/<snapshot_name>/rollback :param volume_name: volume that is going to be restored :param snapshot_name: snapshot of a volume above :return: """ req = ('/volumes/%(vol)s/snapshots/' '%(snap)s/rollback') % {'vol': volume_name, 'snap': snapshot_name} LOG.debug("rollback volume %(vol)s to snapshot %(snap)s", {'vol': volume_name, 'snap': snapshot_name}) resp = self.rproxy.pool_request('POST', req) if not resp["error"] and resp["code"] == 200: return if resp["code"] == 500: if resp["error"]: if resp["error"]["errno"] == 1: raise jexc.JDSSResourceNotFoundException( res="%(vol)s@%(snap)s" % {'vol': volume_name, 'snap': snapshot_name}) self._general_error(req, resp)
def detach_target_vol(self, target_name, lun_name): """detach_target_vol. DELETE /san/iscsi/targets/<target_name>/luns/ <lun_name> :param target_name: :param lun_name: :return: """ req = '/san/iscsi/targets/%(tar)s/luns/%(lun)s' % { 'tar': target_name, 'lun': lun_name} LOG.debug("detach volume %(vol)s from target %(tar)s", {'vol': lun_name, 'tar': target_name}) resp = self.rproxy.pool_request('DELETE', req) if resp["code"] in (200, 201, 204): return if resp['code'] == 404: raise jexc.JDSSResourceNotFoundException(res=lun_name) self._general_error(req, resp)
def delete_target(self, target_name): """delete_target. DELETE /san/iscsi/targets/<target_name> :param pool_name: :param target_name: :return: """ req = '/san/iscsi/targets/' + target_name LOG.debug("delete target %s", target_name) resp = self.rproxy.pool_request('DELETE', req) if resp["code"] in (200, 201, 204): LOG.debug( "target %s deleted", target_name) return not_found_err = "opene.exceptions.ItemNotFoundError" if (resp["code"] == 404) or \ (resp["error"]["class"] == not_found_err): raise jexc.JDSSResourceNotFoundException(res=target_name) self._general_error(req, resp)
def attach_target_vol(self, target_name, lun_name, lun_id=0): """attach_target_vol. POST /san/iscsi/targets/<target_name>/luns :param target_name: :param lun_name: :return: """ req = '/san/iscsi/targets/%s/luns' % target_name jbody = {"name": lun_name, "lun": lun_id} LOG.debug("atach volume %(vol)s to target %(tar)s", {'vol': lun_name, 'tar': target_name}) resp = self.rproxy.pool_request('POST', req, json_data=jbody) if not resp["error"] and resp["code"] == 201: return if resp['code'] == 409: raise jexc.JDSSResourceExistsException(res=lun_name) if resp['code'] == 404: raise jexc.JDSSResourceNotFoundException(res=target_name) self._general_error(req, resp)
def create_target_user(self, target_name, chap_cred): """Set CHAP credentials for accees specific target. POST /san/iscsi/targets/<target_name>/incoming-users :param target_name: :param chap_cred: { "name": "target_user", "password": "******" --- 12 chars min } :return: """ req = "/san/iscsi/targets/%s/incoming-users" % target_name LOG.debug("add credentails to target %s", target_name) resp = self.rproxy.pool_request('POST', req, json_data=chap_cred) if not resp["error"] and resp["code"] in (200, 201, 204): return if resp['code'] == 404: raise jexc.JDSSResourceNotFoundException(res=target_name) self._general_error(req, resp)
def modify_lun(self, volume_name, prop=None): """Update volume properties :prop volume_name: volume name :prop prop: dictionary { <property>: <value> } """ req = '/volumes/' + volume_name resp = self.rproxy.pool_request('PUT', req, json_data=prop) if resp["code"] in (200, 201, 204): LOG.debug("volume %s 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) self._general_error(req, resp)
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 get_lun(self, volume_name): """get_lun. GET /volumes/<volume_name> :param volume_name: :return: { "data": { "origin": null, "referenced": "65536", "primarycache": "all", "logbias": "latency", "creation": "1432730973", "sync": "always", "is_clone": false, "dedup": "off", "used": "1076101120", "full_name": "Pool-0/v1", "type": "volume", "written": "65536", "usedbyrefreservation": "1076035584", "compression": "lz4", "usedbysnapshots": "0", "copies": "1", "compressratio": "1.00x", "readonly": "off", "mlslabel": "none", "secondarycache": "all", "available": "976123452576", "resource_name": "Pool-0/v1", "volblocksize": "131072", "refcompressratio": "1.00x", "snapdev": "hidden", "volsize": "1073741824", "reservation": "0", "usedbychildren": "0", "usedbydataset": "65536", "name": "v1", "checksum": "on", "refreservation": "1076101120" }, "error": null } """ req = '/volumes/' + volume_name LOG.debug("get volume %s info", volume_name) resp = self.rproxy.pool_request('GET', req) if not resp['error'] and resp['code'] == 200: return resp['data'] if resp['error']: if 'message' in resp['error']: if self.resource_dne_msg.match(resp['error']['message']): raise jexc.JDSSResourceNotFoundException(res=volume_name) self._general_error(req, resp)
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/%s/snapshots' % volume_name 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) self._general_error(req, resp)
def test_remove_target_volume_no_target(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.detach_target_vol.side_effect = ( jexc.JDSSResourceNotFoundException(res=target_name)) jdssd.ra.delete_target.return_value = None 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 test_clone_object_dne(self): jdssd, ctx = self.get_driver(CONFIG_OK) calls = [] origin = jcom.vname(UUID_1) clone = jcom.vname(UUID_2) calls.append(mock.call(origin, clone)) jdssd.ra.create_snapshot.side_effect = ( jexc.JDSSResourceNotFoundException(res=origin)) self.assertRaises(exception.VolumeNotFound, jdssd._clone_object, origin, clone) origin = jcom.sname(UUID_1) calls.append(mock.call(origin, clone)) self.assertRaises(exception.SnapshotNotFound, jdssd._clone_object, origin, clone) jdssd.ra.create_snapshot.assert_has_calls(calls)
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/%s/clone' % original_vol_name 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) if resp["error"]["errno"] == 1: raise jexc.JDSSResourceNotFoundException( res="%(vol)s@%(snap)s" % {'vol': original_vol_name, 'snap': snapshot_name}) self._general_error(req, resp)
def get_target_user(self, target_name): """Get name of CHAP user for accessing target GET /san/iscsi/targets/<target_name>/incoming-users :param target_name: """ req = "/san/iscsi/targets/%s/incoming-users" % target_name LOG.debug("get chap cred for target %s", target_name) resp = self.rproxy.pool_request('GET', req) if not resp["error"] and resp["code"] == 200: return resp['data'] if resp['code'] == 404: raise jexc.JDSSResourceNotFoundException(res=target_name) self._general_error(req, resp)
def delete_target_user(self, target_name, user_name): """Delete CHAP user for target DELETE /san/iscsi/targets/<target_name>/incoming-users/<user_name> :param target_name: target name :param user_name: user name """ req = '/san/iscsi/targets/{0}/incoming-users/{1}'.format( target_name, user_name) LOG.debug("remove credentails from target %s", target_name) resp = self.rproxy.pool_request('DELETE', req) if resp["error"] is None and resp["code"] == 204: return if resp['code'] == 404: raise jexc.JDSSResourceNotFoundException(res=target_name) self._general_error(req, resp)