]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Removing Nexenta driver for no reported CI
authorMike Perez <thingee@gmail.com>
Thu, 19 Mar 2015 17:51:36 +0000 (10:51 -0700)
committerMike Perez <thingee@gmail.com>
Thu, 19 Mar 2015 19:28:34 +0000 (12:28 -0700)
CI deadlines were set and pushed since last year. An email about this
requirement and the deadline of March 19th 2015 has been sent to each
individual driver maintainer, as well as the mailing list [1]. This
driver is being removed because the maintainer does not have a CI
reporting to ensure their driver integration is successful. Therfore, we
can not validate the driver is working in Cinder today in a continuous
way.

DocImpact
[1]- http://lists.openstack.org/pipermail/openstack-dev/2015-January/054614.html

Change-Id: I732612e671c57c0b611f1016f22c89a886a317f7

cinder/tests/test_nexenta.py [deleted file]
cinder/volume/drivers/nexenta/__init__.py [deleted file]
cinder/volume/drivers/nexenta/iscsi.py [deleted file]
cinder/volume/drivers/nexenta/jsonrpc.py [deleted file]
cinder/volume/drivers/nexenta/nfs.py [deleted file]
cinder/volume/drivers/nexenta/options.py [deleted file]
cinder/volume/drivers/nexenta/utils.py [deleted file]

diff --git a/cinder/tests/test_nexenta.py b/cinder/tests/test_nexenta.py
deleted file mode 100644 (file)
index 106bbe7..0000000
+++ /dev/null
@@ -1,783 +0,0 @@
-#
-# Copyright 2011 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-Unit tests for OpenStack Cinder volume driver
-"""
-
-import base64
-import urllib2
-
-import mox as mox_lib
-from oslo_utils import units
-
-from cinder import context
-from cinder import db
-from cinder import test
-from cinder.volume import configuration as conf
-from cinder.volume.drivers import nexenta
-from cinder.volume.drivers.nexenta import iscsi
-from cinder.volume.drivers.nexenta import jsonrpc
-from cinder.volume.drivers.nexenta import nfs
-from cinder.volume.drivers.nexenta import utils
-
-
-class TestNexentaISCSIDriver(test.TestCase):
-    TEST_VOLUME_NAME = 'volume1'
-    TEST_VOLUME_NAME2 = 'volume2'
-    TEST_SNAPSHOT_NAME = 'snapshot1'
-    TEST_VOLUME_REF = {
-        'name': TEST_VOLUME_NAME,
-        'size': 1,
-        'id': '1',
-        'status': 'available'
-    }
-    TEST_VOLUME_REF2 = {
-        'name': TEST_VOLUME_NAME2,
-        'size': 1,
-        'id': '2',
-        'status': 'in-use'
-    }
-    TEST_SNAPSHOT_REF = {
-        'name': TEST_SNAPSHOT_NAME,
-        'volume_name': TEST_VOLUME_NAME,
-    }
-
-    def __init__(self, method):
-        super(TestNexentaISCSIDriver, self).__init__(method)
-
-    def setUp(self):
-        super(TestNexentaISCSIDriver, self).setUp()
-        self.configuration = mox_lib.MockObject(conf.Configuration)
-        self.configuration.nexenta_host = '1.1.1.1'
-        self.configuration.nexenta_user = 'admin'
-        self.configuration.nexenta_password = 'nexenta'
-        self.configuration.nexenta_volume = 'cinder'
-        self.configuration.nexenta_rest_port = 2000
-        self.configuration.nexenta_rest_protocol = 'http'
-        self.configuration.nexenta_iscsi_target_portal_port = 3260
-        self.configuration.nexenta_target_prefix = 'iqn:'
-        self.configuration.nexenta_target_group_prefix = 'cinder/'
-        self.configuration.nexenta_blocksize = '8K'
-        self.configuration.nexenta_sparse = True
-        self.configuration.nexenta_rrmgr_compression = 1
-        self.configuration.nexenta_rrmgr_tcp_buf_size = 1024
-        self.configuration.nexenta_rrmgr_connections = 2
-        self.nms_mock = self.mox.CreateMockAnything()
-        for mod in ['volume', 'zvol', 'iscsitarget', 'appliance',
-                    'stmf', 'scsidisk', 'snapshot']:
-            setattr(self.nms_mock, mod, self.mox.CreateMockAnything())
-        self.stubs.Set(jsonrpc, 'NexentaJSONProxy',
-                       lambda *_, **__: self.nms_mock)
-        self.drv = iscsi.NexentaISCSIDriver(configuration=self.configuration)
-        self.drv.do_setup({})
-
-    def test_setup_error(self):
-        self.nms_mock.volume.object_exists('cinder').AndReturn(True)
-        self.mox.ReplayAll()
-        self.drv.check_for_setup_error()
-
-    def test_setup_error_fail(self):
-        self.nms_mock.volume.object_exists('cinder').AndReturn(False)
-        self.mox.ReplayAll()
-        self.assertRaises(LookupError, self.drv.check_for_setup_error)
-
-    def test_local_path(self):
-        self.assertRaises(NotImplementedError, self.drv.local_path, '')
-
-    def test_create_volume(self):
-        self.nms_mock.zvol.create('cinder/volume1', '1G', '8K', True)
-        self.nms_mock.stmf.list_targets()
-        self.nms_mock.iscsitarget.create_target({'target_name': 'iqn:volume1'})
-        self.nms_mock.stmf.list_targetgroups()
-        self.nms_mock.stmf.create_targetgroup('cinder/volume1')
-        self.nms_mock.stmf.list_targetgroup_members('cinder/volume1')
-        self.nms_mock.stmf.add_targetgroup_member('cinder/volume1',
-                                                  'iqn:volume1')
-        self.nms_mock.scsidisk.lu_exists('cinder/volume1')
-        self.nms_mock.scsidisk.create_lu('cinder/volume1', {})
-        self.nms_mock.scsidisk.lu_shared('cinder/volume1')
-        self.nms_mock.scsidisk.add_lun_mapping_entry(
-            'cinder/volume1', {'target_group': 'cinder/volume1'})
-        self.mox.ReplayAll()
-        self.drv.create_volume(self.TEST_VOLUME_REF)
-
-    def test_delete_volume(self):
-        self.nms_mock.zvol.get_child_props('cinder/volume1',
-                                           'origin').AndReturn({})
-        self.nms_mock.zvol.destroy('cinder/volume1', '')
-        self.mox.ReplayAll()
-        self.drv.delete_volume(self.TEST_VOLUME_REF)
-        self.mox.ResetAll()
-
-        c = self.nms_mock.zvol.get_child_props('cinder/volume1', 'origin')
-        c.AndReturn({'origin': 'cinder/volume0@snapshot'})
-        self.nms_mock.zvol.destroy('cinder/volume1', '')
-        self.mox.ReplayAll()
-        self.drv.delete_volume(self.TEST_VOLUME_REF)
-        self.mox.ResetAll()
-
-        c = self.nms_mock.zvol.get_child_props('cinder/volume1', 'origin')
-        c.AndReturn({'origin': 'cinder/volume0@cinder-clone-snapshot-1'})
-        self.nms_mock.zvol.destroy('cinder/volume1', '')
-        self.nms_mock.snapshot.destroy(
-            'cinder/volume0@cinder-clone-snapshot-1', '')
-        self.mox.ReplayAll()
-        self.drv.delete_volume(self.TEST_VOLUME_REF)
-        self.mox.ResetAll()
-
-    def test_create_cloned_volume(self):
-        vol = self.TEST_VOLUME_REF2
-        src_vref = self.TEST_VOLUME_REF
-        snapshot = {
-            'volume_name': src_vref['name'],
-            'name': 'cinder-clone-snapshot-%s' % vol['id'],
-        }
-        self.nms_mock.zvol.create_snapshot('cinder/%s' % src_vref['name'],
-                                           snapshot['name'], '')
-        self.nms_mock.zvol.clone('cinder/%s@%s' % (src_vref['name'],
-                                                   snapshot['name']),
-                                 'cinder/%s' % vol['name'])
-        self.mox.ReplayAll()
-        self.drv.create_cloned_volume(vol, src_vref)
-
-    def test_migrate_volume(self):
-        volume = self.TEST_VOLUME_REF
-        host = {
-            'capabilities': {
-                'vendor_name': 'Nexenta',
-                'location_info': 'NexentaISCSIDriver:1.1.1.1:cinder',
-                'free_capacity_gb': 1,
-                'iscsi_target_portal_port': 3260,
-                'nms_url': 'http://admin:password@1.1.1.1:2000'
-            }
-        }
-        snapshot = {
-            'volume_name': volume['name'],
-            'name': 'cinder-migrate-snapshot-%s' % volume['id'],
-        }
-        self.nms_mock.appliance.ssh_list_bindings().AndReturn([])
-        self.nms_mock.zvol.create_snapshot('cinder/%s' % volume['name'],
-                                           snapshot['name'], '')
-
-        src = '%(volume)s/%(zvol)s@%(snapshot)s' % {
-            'volume': 'cinder',
-            'zvol': volume['name'],
-            'snapshot': snapshot['name']
-        }
-        dst = '1.1.1.1:cinder'
-        cmd = ' '.join(['rrmgr -s zfs -c 1 -q -e -w 1024 -n 2', src, dst])
-
-        self.nms_mock.appliance.execute(cmd)
-
-        snapshot_name = 'cinder/%(volume)s@%(snapshot)s' % {
-            'volume': volume['name'],
-            'snapshot': snapshot['name']
-        }
-        self.nms_mock.snapshot.destroy(snapshot_name, '')
-        volume_name = 'cinder/%s' % volume['name']
-        self.nms_mock.zvol.get_child_props(volume_name,
-                                           'origin').AndReturn(None)
-        self.nms_mock.zvol.destroy(volume_name, '')
-        self.nms_mock.snapshot.destroy('cinder/%(volume)s@%(snapshot)s' % {
-            'volume': volume['name'],
-            'snapshot': snapshot['name']
-        }, '')
-
-        self.mox.ReplayAll()
-        self.drv.migrate_volume(None, volume, host)
-
-    def test_create_snapshot(self):
-        self.nms_mock.zvol.create_snapshot('cinder/volume1', 'snapshot1', '')
-        self.mox.ReplayAll()
-        self.drv.create_snapshot(self.TEST_SNAPSHOT_REF)
-
-    def test_create_volume_from_snapshot(self):
-        self.nms_mock.zvol.clone('cinder/volume1@snapshot1', 'cinder/volume2')
-        self.mox.ReplayAll()
-        self.drv.create_volume_from_snapshot(self.TEST_VOLUME_REF2,
-                                             self.TEST_SNAPSHOT_REF)
-
-    def test_delete_snapshot(self):
-        self.nms_mock.snapshot.destroy('cinder/volume1@snapshot1', '')
-        self.mox.ReplayAll()
-        self.drv.delete_snapshot(self.TEST_SNAPSHOT_REF)
-        self.mox.ResetAll()
-
-        # Check that exception not raised if snapshot does not exist
-        mock = self.nms_mock.snapshot.destroy('cinder/volume1@snapshot1', '')
-        mock.AndRaise(nexenta.NexentaException(
-            'Snapshot cinder/volume1@snapshot1 does not exist'))
-        self.mox.ReplayAll()
-        self.drv.delete_snapshot(self.TEST_SNAPSHOT_REF)
-
-    _CREATE_EXPORT_METHODS = [
-        ('stmf', 'list_targets', tuple(), [], False, ),
-        ('iscsitarget', 'create_target', ({'target_name': 'iqn:volume1'},),
-            u'Unable to create iscsi target\n'
-            u' iSCSI target iqn.1986-03.com.sun:02:cinder-volume1 already'
-            u' configured\n'
-            u' itadm create-target failed with error 17\n', True, ),
-        ('stmf', 'list_targetgroups', tuple(), [], False, ),
-        ('stmf', 'create_targetgroup', ('cinder/volume1',),
-            u'Unable to create targetgroup: stmfadm: cinder/volume1:'
-            u' already exists\n', True, ),
-        ('stmf', 'list_targetgroup_members', ('cinder/volume1', ), [],
-         False, ),
-        ('stmf', 'add_targetgroup_member', ('cinder/volume1', 'iqn:volume1'),
-            u'Unable to add member to targetgroup: stmfadm:'
-            u' iqn.1986-03.com.sun:02:cinder-volume1: already exists\n',
-            True, ),
-        ('scsidisk', 'lu_exists', ('cinder/volume1', ), 0, False, ),
-        ('scsidisk', 'create_lu', ('cinder/volume1', {}),
-            u"Unable to create lu with zvol 'cinder/volume1':\n"
-            u" sbdadm: filename /dev/zvol/rdsk/cinder/volume1: in use\n",
-            True, ),
-        ('scsidisk', 'lu_shared', ('cinder/volume1', ), 0, False, ),
-        ('scsidisk', 'add_lun_mapping_entry', ('cinder/volume1', {
-            'target_group': 'cinder/volume1'}),
-            u"Unable to add view to zvol 'cinder/volume1' (LUNs in use: ):\n"
-            u" stmfadm: view entry exists\n", True, ),
-    ]
-
-    def _stub_export_method(self, module, method, args, error, raise_exception,
-                            fail=False):
-        m = getattr(self.nms_mock, module)
-        m = getattr(m, method)
-        mock = m(*args)
-        if raise_exception and fail:
-            mock.AndRaise(nexenta.NexentaException(error))
-        else:
-            mock.AndReturn(error)
-
-    def _stub_all_export_methods(self, fail=False):
-        for params in self._CREATE_EXPORT_METHODS:
-            self._stub_export_method(*params, fail=fail)
-
-    def test_create_export(self):
-        self._stub_all_export_methods()
-        self.mox.ReplayAll()
-        retval = self.drv.create_export({}, self.TEST_VOLUME_REF)
-        location = '%(host)s:%(port)s,1 %(prefix)s%(volume)s 0' % {
-            'host': self.configuration.nexenta_host,
-            'port': self.configuration.nexenta_iscsi_target_portal_port,
-            'prefix': self.configuration.nexenta_target_prefix,
-            'volume': self.TEST_VOLUME_NAME
-        }
-        self.assertEqual(retval, {'provider_location': location})
-
-    def __get_test(i):
-        def _test_create_export_fail(self):
-            for params in self._CREATE_EXPORT_METHODS[:i]:
-                self._stub_export_method(*params)
-            self._stub_export_method(*self._CREATE_EXPORT_METHODS[i],
-                                     fail=True)
-            self.mox.ReplayAll()
-            self.assertRaises(nexenta.NexentaException,
-                              self.drv.create_export,
-                              {},
-                              self.TEST_VOLUME_REF)
-        return _test_create_export_fail
-
-    for i in range(len(_CREATE_EXPORT_METHODS)):
-        if i % 2:
-            locals()['test_create_export_fail_%d' % i] = __get_test(i)
-
-    def test_ensure_export(self):
-        self._stub_all_export_methods(fail=True)
-        self.mox.ReplayAll()
-        self.drv.ensure_export({}, self.TEST_VOLUME_REF)
-
-    def test_remove_export(self):
-        self.nms_mock.scsidisk.delete_lu('cinder/volume1')
-        self.nms_mock.stmf.destroy_targetgroup('cinder/volume1')
-        self.nms_mock.iscsitarget.delete_target('iqn:volume1')
-        self.mox.ReplayAll()
-        self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
-    def test_remove_export_fail_0(self):
-        self.nms_mock.scsidisk.delete_lu('cinder/volume1')
-        self.nms_mock.stmf.destroy_targetgroup(
-            'cinder/volume1').AndRaise(nexenta.NexentaException())
-        self.nms_mock.iscsitarget.delete_target('iqn:volume1')
-        self.mox.ReplayAll()
-        self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
-    def test_remove_export_fail_1(self):
-        self.nms_mock.scsidisk.delete_lu('cinder/volume1')
-        self.nms_mock.stmf.destroy_targetgroup('cinder/volume1')
-        self.nms_mock.iscsitarget.delete_target(
-            'iqn:volume1').AndRaise(nexenta.NexentaException())
-        self.mox.ReplayAll()
-        self.drv.remove_export({}, self.TEST_VOLUME_REF)
-
-    def test_get_volume_stats(self):
-        stats = {'size': '5368709120G',
-                 'used': '5368709120G',
-                 'available': '5368709120G',
-                 'health': 'ONLINE'}
-        self.nms_mock.volume.get_child_props(
-            self.configuration.nexenta_volume,
-            'health|size|used|available').AndReturn(stats)
-        self.mox.ReplayAll()
-        stats = self.drv.get_volume_stats(True)
-        self.assertEqual(stats['storage_protocol'], 'iSCSI')
-        self.assertEqual(stats['total_capacity_gb'], 5368709120.0)
-        self.assertEqual(stats['free_capacity_gb'], 5368709120.0)
-        self.assertEqual(stats['reserved_percentage'], 0)
-        self.assertEqual(stats['QoS_support'], False)
-
-
-class TestNexentaJSONRPC(test.TestCase):
-    HOST = 'example.com'
-    URL = 'http://%s/' % HOST
-    URL_S = 'https://%s/' % HOST
-    USER = 'user'
-    PASSWORD = 'password'
-    HEADERS = {
-        'Authorization':
-        'Basic %s' % base64.b64encode('%s:%s' % (USER, PASSWORD)),
-        'Content-Type': 'application/json'
-    }
-    REQUEST = 'the request'
-
-    def setUp(self):
-        super(TestNexentaJSONRPC, self).setUp()
-        self.proxy = jsonrpc.NexentaJSONProxy(
-            'http', self.HOST, 2000, '/', self.USER, self.PASSWORD, auto=True)
-        self.mox.StubOutWithMock(urllib2, 'Request', True)
-        self.mox.StubOutWithMock(urllib2, 'urlopen')
-        self.resp_mock = self.mox.CreateMockAnything()
-        self.resp_info_mock = self.mox.CreateMockAnything()
-        self.resp_mock.info().AndReturn(self.resp_info_mock)
-        urllib2.urlopen(self.REQUEST).AndReturn(self.resp_mock)
-
-    def test_call(self):
-        urllib2.Request(
-            'http://%s:2000/' % self.HOST,
-            '{"object": null, "params": ["arg1", "arg2"], "method": null}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        self.resp_info_mock.status = ''
-        self.resp_mock.read().AndReturn(
-            '{"error": null, "result": "the result"}')
-        self.mox.ReplayAll()
-        result = self.proxy('arg1', 'arg2')
-        self.assertEqual("the result", result)
-
-    def test_call_deep(self):
-        urllib2.Request(
-            'http://%s:2000/' % self.HOST,
-            '{"object": "obj1.subobj", "params": ["arg1", "arg2"],'
-            ' "method": "meth"}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        self.resp_info_mock.status = ''
-        self.resp_mock.read().AndReturn(
-            '{"error": null, "result": "the result"}')
-        self.mox.ReplayAll()
-        result = self.proxy.obj1.subobj.meth('arg1', 'arg2')
-        self.assertEqual("the result", result)
-
-    def test_call_auto(self):
-        urllib2.Request(
-            'http://%s:2000/' % self.HOST,
-            '{"object": null, "params": ["arg1", "arg2"], "method": null}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        urllib2.Request(
-            'https://%s:2000/' % self.HOST,
-            '{"object": null, "params": ["arg1", "arg2"], "method": null}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        self.resp_info_mock.status = 'EOF in headers'
-        self.resp_mock.read().AndReturn(
-            '{"error": null, "result": "the result"}')
-        urllib2.urlopen(self.REQUEST).AndReturn(self.resp_mock)
-        self.mox.ReplayAll()
-        result = self.proxy('arg1', 'arg2')
-        self.assertEqual("the result", result)
-
-    def test_call_error(self):
-        urllib2.Request(
-            'http://%s:2000/' % self.HOST,
-            '{"object": null, "params": ["arg1", "arg2"], "method": null}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        self.resp_info_mock.status = ''
-        self.resp_mock.read().AndReturn(
-            '{"error": {"message": "the error"}, "result": "the result"}')
-        self.mox.ReplayAll()
-        self.assertRaises(jsonrpc.NexentaJSONException,
-                          self.proxy, 'arg1', 'arg2')
-
-    def test_call_fail(self):
-        urllib2.Request(
-            'http://%s:2000/' % self.HOST,
-            '{"object": null, "params": ["arg1", "arg2"], "method": null}',
-            self.HEADERS).AndReturn(self.REQUEST)
-        self.resp_info_mock.status = 'EOF in headers'
-        self.proxy.auto = False
-        self.mox.ReplayAll()
-        self.assertRaises(jsonrpc.NexentaJSONException,
-                          self.proxy, 'arg1', 'arg2')
-
-
-class TestNexentaNfsDriver(test.TestCase):
-    TEST_EXPORT1 = 'host1:/volumes/stack/share'
-    TEST_NMS1 = 'http://admin:nexenta@host1:2000'
-
-    TEST_EXPORT2 = 'host2:/volumes/stack/share'
-    TEST_NMS2 = 'http://admin:nexenta@host2:2000'
-
-    TEST_EXPORT2_OPTIONS = '-o intr'
-
-    TEST_FILE_NAME = 'test.txt'
-    TEST_SHARES_CONFIG_FILE = '/etc/cinder/nexenta-shares.conf'
-
-    TEST_SHARE_SVC = 'svc:/network/nfs/server:default'
-
-    TEST_SHARE_OPTS = {
-        'read_only': '',
-        'read_write': '*',
-        'recursive': 'true',
-        'anonymous_rw': 'true',
-        'extra_options': 'anon=0',
-        'root': 'nobody'
-    }
-
-    def _create_volume_db_entry(self):
-        vol = {
-            'id': '1',
-            'size': 1,
-            'status': 'available',
-            'provider_location': self.TEST_EXPORT1
-        }
-        return db.volume_create(self.ctxt, vol)['id']
-
-    def setUp(self):
-        super(TestNexentaNfsDriver, self).setUp()
-        self.ctxt = context.get_admin_context()
-        self.configuration = mox_lib.MockObject(conf.Configuration)
-        self.configuration.nexenta_shares_config = None
-        self.configuration.nexenta_mount_point_base = '$state_path/mnt'
-        self.configuration.nexenta_sparsed_volumes = True
-        self.configuration.nexenta_volume_compression = 'on'
-        self.configuration.nfs_mount_point_base = '/mnt/test'
-        self.configuration.nfs_mount_options = None
-        self.configuration.nas_mount_options = None
-        self.configuration.nexenta_nms_cache_volroot = False
-        self.nms_mock = self.mox.CreateMockAnything()
-        for mod in ('appliance', 'folder', 'server', 'volume', 'netstorsvc',
-                    'snapshot'):
-            setattr(self.nms_mock, mod, self.mox.CreateMockAnything())
-        self.nms_mock.__hash__ = lambda *_, **__: 1
-        self.stubs.Set(jsonrpc, 'NexentaJSONProxy',
-                       lambda *_, **__: self.nms_mock)
-        self.drv = nfs.NexentaNfsDriver(configuration=self.configuration)
-        self.drv.shares = {}
-        self.drv.share2nms = {}
-
-    def test_check_for_setup_error(self):
-        self.drv.share2nms = {
-            'host1:/volumes/stack/share': self.nms_mock
-        }
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.volume.object_exists('stack').AndReturn(True)
-        self.nms_mock.folder.object_exists('stack/share').AndReturn(True)
-        share_opts = {
-            'read_write': '*',
-            'read_only': '',
-            'root': 'nobody',
-            'extra_options': 'anon=0',
-            'recursive': 'true',
-            'anonymous_rw': 'true',
-        }
-        self.nms_mock.netstorsvc.share_folder(
-            'svc:/network/nfs/server:default', 'stack/share', share_opts)
-
-        self.mox.ReplayAll()
-
-        self.drv.check_for_setup_error()
-
-        self.mox.ResetAll()
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.volume.object_exists('stack').AndReturn(False)
-
-        self.mox.ReplayAll()
-
-        self.assertRaises(LookupError, self.drv.check_for_setup_error)
-
-        self.mox.ResetAll()
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.volume.object_exists('stack').AndReturn(True)
-        self.nms_mock.folder.object_exists('stack/share').AndReturn(False)
-
-        self.mox.ReplayAll()
-
-        self.assertRaises(LookupError, self.drv.check_for_setup_error)
-
-    def test_initialize_connection(self):
-        self.drv.shares = {
-            self.TEST_EXPORT1: None
-        }
-        volume = {
-            'provider_location': self.TEST_EXPORT1,
-            'name': 'volume'
-        }
-        result = self.drv.initialize_connection(volume, None)
-        self.assertEqual(result['data']['export'],
-                         '%s/volume' % self.TEST_EXPORT1)
-
-    def test_do_create_volume(self):
-        volume = {
-            'provider_location': self.TEST_EXPORT1,
-            'size': 1,
-            'name': 'volume-1'
-        }
-        self.drv.shares = {self.TEST_EXPORT1: None}
-        self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
-
-        compression = self.configuration.nexenta_volume_compression
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.folder.create_with_props(
-            'stack', 'share/volume-1', {'compression': compression})
-        self.nms_mock.netstorsvc.share_folder(self.TEST_SHARE_SVC,
-                                              'stack/share/volume-1',
-                                              self.TEST_SHARE_OPTS)
-        self.nms_mock.appliance.execute(
-            'truncate --size 1G /volumes/stack/share/volume-1/volume')
-        self.nms_mock.appliance.execute('chmod ugo+rw '
-                                        '/volumes/stack/share/volume-1/volume')
-
-        self.mox.ReplayAll()
-
-        self.drv._do_create_volume(volume)
-
-        self.mox.ResetAll()
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.folder.create_with_props(
-            'stack', 'share/volume-1', {'compression': compression})
-        self.nms_mock.netstorsvc.share_folder(
-            self.TEST_SHARE_SVC, 'stack/share/volume-1',
-            self.TEST_SHARE_OPTS).AndRaise(nexenta.NexentaException('-'))
-        self.nms_mock.folder.destroy('stack/share/volume-1')
-
-        self.mox.ReplayAll()
-
-        self.assertRaises(nexenta.NexentaException, self.drv._do_create_volume,
-                          volume)
-
-    def test_create_sparsed_file(self):
-        self.nms_mock.appliance.execute('truncate --size 1G /tmp/path')
-        self.mox.ReplayAll()
-
-        self.drv._create_sparsed_file(self.nms_mock, '/tmp/path', 1)
-
-    def test_create_regular_file(self):
-        self.nms_mock.appliance.execute('dd if=/dev/zero of=/tmp/path bs=1M '
-                                        'count=1024')
-        self.mox.ReplayAll()
-
-        self.drv._create_regular_file(self.nms_mock, '/tmp/path', 1)
-
-    def test_set_rw_permissions_for_all(self):
-        path = '/tmp/path'
-        self.nms_mock.appliance.execute('chmod ugo+rw %s' % path)
-        self.mox.ReplayAll()
-
-        self.drv._set_rw_permissions_for_all(self.nms_mock, path)
-
-    def test_local_path(self):
-        volume = {'provider_location': self.TEST_EXPORT1, 'name': 'volume-1'}
-        path = self.drv.local_path(volume)
-        self.assertEqual(
-            path,
-            '$state_path/mnt/b3f660847a52b29ac330d8555e4ad669/volume-1/volume'
-        )
-
-    def test_remote_path(self):
-        volume = {'provider_location': self.TEST_EXPORT1, 'name': 'volume-1'}
-        path = self.drv.remote_path(volume)
-        self.assertEqual(path, '/volumes/stack/share/volume-1/volume')
-
-    def test_share_folder(self):
-        path = 'stack/share/folder'
-        self.nms_mock.netstorsvc.share_folder(self.TEST_SHARE_SVC, path,
-                                              self.TEST_SHARE_OPTS)
-        self.mox.ReplayAll()
-
-        self.drv._share_folder(self.nms_mock, 'stack', 'share/folder')
-
-    def test_load_shares_config(self):
-        self.drv.configuration.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE
-
-        self.mox.StubOutWithMock(self.drv, '_read_config_file')
-        config_data = [
-            '%s  %s' % (self.TEST_EXPORT1, self.TEST_NMS1),
-            '# %s   %s' % (self.TEST_EXPORT2, self.TEST_NMS2),
-            '',
-            '%s  %s %s' % (self.TEST_EXPORT2, self.TEST_NMS2,
-                           self.TEST_EXPORT2_OPTIONS)
-        ]
-
-        self.drv._read_config_file(self.TEST_SHARES_CONFIG_FILE).\
-            AndReturn(config_data)
-        self.mox.ReplayAll()
-
-        self.drv._load_shares_config(self.drv.configuration.nfs_shares_config)
-
-        self.assertIn(self.TEST_EXPORT1, self.drv.shares)
-        self.assertIn(self.TEST_EXPORT2, self.drv.shares)
-        self.assertEqual(len(self.drv.shares), 2)
-
-        self.assertIn(self.TEST_EXPORT1, self.drv.share2nms)
-        self.assertIn(self.TEST_EXPORT2, self.drv.share2nms)
-        self.assertEqual(len(self.drv.share2nms.keys()), 2)
-
-        self.assertEqual(self.drv.shares[self.TEST_EXPORT2],
-                         self.TEST_EXPORT2_OPTIONS)
-
-        self.mox.VerifyAll()
-
-    def test_get_capacity_info(self):
-        self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.folder.get_child_props('stack/share', '').AndReturn({
-            'available': '1G',
-            'used': '2G'
-        })
-        self.mox.ReplayAll()
-        total, free, allocated = self.drv._get_capacity_info(self.TEST_EXPORT1)
-
-        self.assertEqual(total, 3 * units.Gi)
-        self.assertEqual(free, units.Gi)
-        self.assertEqual(allocated, 2 * units.Gi)
-
-    def test_get_share_datasets(self):
-        self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.mox.ReplayAll()
-
-        volume_name, folder_name = \
-            self.drv._get_share_datasets(self.TEST_EXPORT1)
-
-        self.assertEqual(volume_name, 'stack')
-        self.assertEqual(folder_name, 'share')
-
-    def test_delete_snapshot(self):
-        self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
-        self._create_volume_db_entry()
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.snapshot.destroy('stack/share/volume-1@snapshot1', '')
-        self.mox.ReplayAll()
-        self.drv.delete_snapshot({'volume_id': '1', 'name': 'snapshot1'})
-        self.mox.ResetAll()
-
-        # Check that exception not raised if snapshot does not exist on
-        # NexentaStor appliance.
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        mock = self.nms_mock.snapshot.destroy('stack/share/volume-1@snapshot1',
-                                              '')
-        mock.AndRaise(nexenta.NexentaException("Snapshot does not exist"))
-        self.mox.ReplayAll()
-        self.drv.delete_snapshot({'volume_id': '1', 'name': 'snapshot1'})
-        self.mox.ResetAll()
-
-    def test_delete_volume(self):
-        self.drv.share2nms = {self.TEST_EXPORT1: self.nms_mock}
-        self._create_volume_db_entry()
-
-        self.drv._ensure_share_mounted = lambda *_, **__: 0
-        self.drv._execute = lambda *_, **__: 0
-
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.folder.get_child_props('stack/share/volume-1',
-                                             'origin').AndReturn(None)
-        self.nms_mock.folder.destroy('stack/share/volume-1', '-r')
-        self.mox.ReplayAll()
-        self.drv.delete_volume({
-            'id': '1',
-            'name': 'volume-1',
-            'provider_location': self.TEST_EXPORT1
-        })
-        self.mox.ResetAll()
-
-        # Check that exception not raised if folder does not exist on
-        # NexentaStor appliance.
-        self.nms_mock.server.get_prop('volroot').AndReturn('/volumes')
-        self.nms_mock.folder.get_child_props('stack/share/volume-1',
-                                             'origin').AndReturn(None)
-        mock = self.nms_mock.folder.destroy('stack/share/volume-1', '-r')
-        mock.AndRaise(nexenta.NexentaException("Folder does not exist"))
-        self.mox.ReplayAll()
-        self.drv.delete_volume({
-            'id': '1',
-            'name': 'volume-1',
-            'provider_location': self.TEST_EXPORT1
-        })
-        self.mox.ResetAll()
-
-
-class TestNexentaUtils(test.TestCase):
-
-    def test_str2size(self):
-        values_to_test = (
-            # Test empty value
-            (None, 0),
-            ('', 0),
-            ('0', 0),
-            ('12', 12),
-            # Test int and long values
-            (10, 10),
-            (long(10), 10),
-            # Test bytes string
-            ('1b', 1),
-            ('1B', 1),
-            ('1023b', 1023),
-            ('0B', 0),
-            # Test other units
-            ('1M', units.Mi),
-            ('1.0M', units.Mi),
-        )
-
-        for value, result in values_to_test:
-            self.assertEqual(utils.str2size(value), result)
-
-        # Invalid format value
-        self.assertRaises(ValueError, utils.str2size, 'A')
-
-    def test_str2gib_size(self):
-        self.assertEqual(utils.str2gib_size('1024M'), 1)
-        self.assertEqual(utils.str2gib_size('300M'),
-                         300 * units.Mi // units.Gi)
-        self.assertEqual(utils.str2gib_size('1.2T'),
-                         1.2 * units.Ti // units.Gi)
-        self.assertRaises(ValueError, utils.str2gib_size, 'A')
-
-    def test_parse_nms_url(self):
-        urls = (
-            ('auto://192.168.1.1/', (True, 'http', 'admin', 'nexenta',
-                                     '192.168.1.1', '2000', '/rest/nms/')),
-            ('http://192.168.1.1/', (False, 'http', 'admin', 'nexenta',
-                                     '192.168.1.1', '2000', '/rest/nms/')),
-            ('http://192.168.1.1:8080', (False, 'http', 'admin', 'nexenta',
-                                         '192.168.1.1', '8080', '/rest/nms/')),
-            ('https://root:password@192.168.1.1:8080',
-             (False, 'https', 'root', 'password', '192.168.1.1', '8080',
-              '/rest/nms/')),
-        )
-        for url, result in urls:
-            self.assertEqual(utils.parse_nms_url(url), result)
diff --git a/cinder/volume/drivers/nexenta/__init__.py b/cinder/volume/drivers/nexenta/__init__.py
deleted file mode 100644 (file)
index 16f48bd..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2011 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta` -- Package contains Nexenta-specific modules
-=====================================================================
-
-.. automodule:: nexenta
-.. moduleauthor:: Yuriy Taraday <yorik.sar@gmail.com>
-.. moduleauthor:: Mikhail Khodos <mikhail.khodos@nexenta.com>
-"""
-
-
-class NexentaException(Exception):
-    pass
diff --git a/cinder/volume/drivers/nexenta/iscsi.py b/cinder/volume/drivers/nexenta/iscsi.py
deleted file mode 100644 (file)
index 722a7f8..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-# Copyright 2011 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta.iscsi` -- Driver to store volumes on Nexenta Appliance
-=====================================================================
-
-.. automodule:: nexenta.volume
-.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
-.. moduleauthor:: Mikhail Khodos <mikhail.khodos@nexenta.com>
-.. moduleauthor:: Yuriy Taraday <yorik.sar@gmail.com>
-"""
-
-from oslo_log import log as logging
-
-from cinder import exception
-from cinder.i18n import _, _LE, _LI, _LW
-from cinder.volume import driver
-from cinder.volume.drivers import nexenta
-from cinder.volume.drivers.nexenta import jsonrpc
-from cinder.volume.drivers.nexenta import options
-from cinder.volume.drivers.nexenta import utils
-
-VERSION = '1.2.1'
-LOG = logging.getLogger(__name__)
-
-
-class NexentaISCSIDriver(driver.ISCSIDriver):  # pylint: disable=R0921
-    """Executes volume driver commands on Nexenta Appliance.
-
-    Version history:
-        1.0.0 - Initial driver version.
-        1.0.1 - Fixed bug #1236626: catch "does not exist" exception of
-                lu_exists.
-        1.1.0 - Changed class name to NexentaISCSIDriver.
-        1.1.1 - Ignore "does not exist" exception of nms.snapshot.destroy.
-        1.1.2 - Optimized create_cloned_volume, replaced zfs send recv with zfs
-                clone.
-        1.1.3 - Extended volume stats provided by _update_volume_stats method.
-        1.2.0 - Added volume migration with storage assist method.
-        1.2.1 - Fixed bug #1263258: now migrate_volume update provider_location
-                of migrated volume; after migrating volume migrate_volume
-                destroy snapshot on migration destination.
-    """
-
-    VERSION = VERSION
-
-    def __init__(self, *args, **kwargs):
-        super(NexentaISCSIDriver, self).__init__(*args, **kwargs)
-        self.nms = None
-        if self.configuration:
-            self.configuration.append_config_values(
-                options.NEXENTA_CONNECTION_OPTIONS)
-            self.configuration.append_config_values(
-                options.NEXENTA_ISCSI_OPTIONS)
-            self.configuration.append_config_values(
-                options.NEXENTA_VOLUME_OPTIONS)
-            self.configuration.append_config_values(
-                options.NEXENTA_RRMGR_OPTIONS)
-        self.nms_protocol = self.configuration.nexenta_rest_protocol
-        self.nms_host = self.configuration.nexenta_host
-        self.nms_port = self.configuration.nexenta_rest_port
-        self.nms_user = self.configuration.nexenta_user
-        self.nms_password = self.configuration.nexenta_password
-        self.volume = self.configuration.nexenta_volume
-        self.rrmgr_compression = self.configuration.nexenta_rrmgr_compression
-        self.rrmgr_tcp_buf_size = self.configuration.nexenta_rrmgr_tcp_buf_size
-        self.rrmgr_connections = self.configuration.nexenta_rrmgr_connections
-        self.iscsi_target_portal_port = \
-            self.configuration.nexenta_iscsi_target_portal_port
-
-    @property
-    def backend_name(self):
-        backend_name = None
-        if self.configuration:
-            backend_name = self.configuration.safe_get('volume_backend_name')
-        if not backend_name:
-            backend_name = self.__class__.__name__
-        return backend_name
-
-    def do_setup(self, context):
-        if self.nms_protocol == 'auto':
-            protocol, auto = 'http', True
-        else:
-            protocol, auto = self.nms_protocol, False
-        self.nms = jsonrpc.NexentaJSONProxy(
-            protocol, self.nms_host, self.nms_port, '/rest/nms', self.nms_user,
-            self.nms_password, auto=auto)
-
-    def check_for_setup_error(self):
-        """Verify that the volume for our zvols exists.
-
-        :raise: :py:exc:`LookupError`
-        """
-        if not self.nms.volume.object_exists(self.volume):
-            raise LookupError(_("Volume %s does not exist in Nexenta SA"),
-                              self.volume)
-
-    def _get_zvol_name(self, volume_name):
-        """Return zvol name that corresponds given volume name."""
-        return '%s/%s' % (self.volume, volume_name)
-
-    def _get_target_name(self, volume_name):
-        """Return iSCSI target name to access volume."""
-        return '%s%s' % (self.configuration.nexenta_target_prefix, volume_name)
-
-    def _get_target_group_name(self, volume_name):
-        """Return Nexenta iSCSI target group name for volume."""
-        return '%s%s' % (self.configuration.nexenta_target_group_prefix,
-                         volume_name)
-
-    @staticmethod
-    def _get_clone_snapshot_name(volume):
-        """Return name for snapshot that will be used to clone the volume."""
-        return 'cinder-clone-snapshot-%(id)s' % volume
-
-    @staticmethod
-    def _is_clone_snapshot_name(snapshot):
-        """Check if snapshot is created for cloning."""
-        name = snapshot.split('@')[-1]
-        return name.startswith('cinder-clone-snapshot-')
-
-    def create_volume(self, volume):
-        """Create a zvol on appliance.
-
-        :param volume: volume reference
-        :return: model update dict for volume reference
-        """
-        self.nms.zvol.create(
-            self._get_zvol_name(volume['name']),
-            '%sG' % (volume['size'],),
-            self.configuration.nexenta_blocksize,
-            self.configuration.nexenta_sparse)
-        return self.create_export(None, volume)
-
-    def extend_volume(self, volume, new_size):
-        """Extend an existing volume.
-
-        :param volume: volume reference
-        :param new_size: volume new size in GB
-        """
-        LOG.info(_LI('Extending volume: %(id)s New size: %(size)s GB'),
-                 {'id': volume['id'], 'size': new_size})
-        self.nms.zvol.set_child_prop(self._get_zvol_name(volume['name']),
-                                     'volsize', '%sG' % new_size)
-
-    def delete_volume(self, volume):
-        """Destroy a zvol on appliance.
-
-        :param volume: volume reference
-        """
-        volume_name = self._get_zvol_name(volume['name'])
-        props = self.nms.zvol.get_child_props(volume_name, 'origin') or {}
-        try:
-            self.nms.zvol.destroy(volume_name, '')
-        except nexenta.NexentaException as exc:
-            if 'does not exist' in exc.args[0]:
-                LOG.info(_LI('Volume %s does not exist, it '
-                             'seems it was already deleted.'), volume_name)
-                return
-            if 'zvol has children' in exc.args[0]:
-                raise exception.VolumeIsBusy(volume_name=volume_name)
-            raise
-        origin = props.get('origin')
-        if origin and self._is_clone_snapshot_name(origin):
-            volume, snapshot = origin.split('@')
-            volume = volume.lstrip('%s/' % self.configuration.nexenta_volume)
-            try:
-                self.delete_snapshot({'volume_name': volume, 'name': snapshot})
-            except nexenta.NexentaException as exc:
-                LOG.warning(_LW('Cannot delete snapshot %(origin)s: %(exc)s'),
-                            {'origin': origin, 'exc': exc})
-
-    def create_cloned_volume(self, volume, src_vref):
-        """Creates a clone of the specified volume.
-
-        :param volume: new volume reference
-        :param src_vref: source volume reference
-        """
-        snapshot = {'volume_name': src_vref['name'],
-                    'name': self._get_clone_snapshot_name(volume)}
-        LOG.debug('Creating temp snapshot of the original volume: '
-                  '%(volume_name)s@%(name)s', snapshot)
-        # We don't delete this snapshot, because this snapshot will be origin
-        # of new volume. This snapshot will be automatically promoted by NMS
-        # when user will delete origin volume. But when cloned volume deleted
-        # we check its origin property and delete source snapshot if needed.
-        self.create_snapshot(snapshot)
-        try:
-            self.create_volume_from_snapshot(volume, snapshot)
-        except nexenta.NexentaException:
-            LOG.error(_LE('Volume creation failed, deleting created snapshot '
-                          '%(volume_name)s@%(name)s'), snapshot)
-            try:
-                self.delete_snapshot(snapshot)
-            except (nexenta.NexentaException, exception.SnapshotIsBusy):
-                LOG.warning(_LW('Failed to delete zfs snapshot '
-                                '%(volume_name)s@%(name)s'), snapshot)
-            raise
-
-    def _get_zfs_send_recv_cmd(self, src, dst):
-        """Returns rrmgr command for source and destination."""
-        return utils.get_rrmgr_cmd(src, dst,
-                                   compression=self.rrmgr_compression,
-                                   tcp_buf_size=self.rrmgr_tcp_buf_size,
-                                   connections=self.rrmgr_connections)
-
-    @staticmethod
-    def get_nms_for_url(url):
-        """Returns initialized nms object for url."""
-        auto, scheme, user, password, host, port, path =\
-            utils.parse_nms_url(url)
-        return jsonrpc.NexentaJSONProxy(scheme, host, port, path, user,
-                                        password, auto=auto)
-
-    def migrate_volume(self, ctxt, volume, host):
-        """Migrate if volume and host are managed by Nexenta appliance.
-
-        :param ctxt: context
-        :param volume: a dictionary describing the volume to migrate
-        :param host: a dictionary describing the host to migrate to
-        """
-        LOG.debug('Enter: migrate_volume: id=%(id)s, host=%(host)s' %
-                  {'id': volume['id'], 'host': host})
-
-        false_ret = (False, None)
-
-        if volume['status'] != 'available':
-            return false_ret
-
-        if 'capabilities' not in host:
-            return false_ret
-
-        capabilities = host['capabilities']
-
-        if 'location_info' not in capabilities or \
-                'iscsi_target_portal_port' not in capabilities or \
-                'nms_url' not in capabilities:
-            return false_ret
-
-        iscsi_target_portal_port = capabilities['iscsi_target_portal_port']
-        nms_url = capabilities['nms_url']
-        dst_parts = capabilities['location_info'].split(':')
-
-        if capabilities.get('vendor_name') != 'Nexenta' or \
-                dst_parts[0] != self.__class__.__name__ or \
-                capabilities['free_capacity_gb'] < volume['size']:
-            return false_ret
-
-        dst_host, dst_volume = dst_parts[1:]
-
-        ssh_bound = False
-        ssh_bindings = self.nms.appliance.ssh_list_bindings()
-        for bind in ssh_bindings:
-            if bind.index(dst_host) != -1:
-                ssh_bound = True
-                break
-        if not ssh_bound:
-            LOG.warning(_LW("Remote NexentaStor appliance at %s should be "
-                            "SSH-bound."), dst_host)
-
-        # Create temporary snapshot of volume on NexentaStor Appliance.
-        snapshot = {
-            'volume_name': volume['name'],
-            'name': utils.get_migrate_snapshot_name(volume)
-        }
-        self.create_snapshot(snapshot)
-
-        src = '%(volume)s/%(zvol)s@%(snapshot)s' % {
-            'volume': self.volume,
-            'zvol': volume['name'],
-            'snapshot': snapshot['name']
-        }
-        dst = ':'.join([dst_host, dst_volume])
-
-        try:
-            self.nms.appliance.execute(self._get_zfs_send_recv_cmd(src, dst))
-        except nexenta.NexentaException as exc:
-            LOG.warning(_LW("Cannot send source snapshot %(src)s to "
-                            "destination %(dst)s. Reason: %(exc)s"),
-                        {'src': src, 'dst': dst, 'exc': exc})
-            return false_ret
-        finally:
-            try:
-                self.delete_snapshot(snapshot)
-            except nexenta.NexentaException as exc:
-                LOG.warning(_LW("Cannot delete temporary source snapshot "
-                                "%(src)s on NexentaStor Appliance: %(exc)s"),
-                            {'src': src, 'exc': exc})
-        try:
-            self.delete_volume(volume)
-        except nexenta.NexentaException as exc:
-            LOG.warning(_LW("Cannot delete source volume %(volume)s on "
-                            "NexentaStor Appliance: %(exc)s"),
-                        {'volume': volume['name'], 'exc': exc})
-
-        dst_nms = self.get_nms_for_url(nms_url)
-        dst_snapshot = '%s/%s@%s' % (dst_volume, volume['name'],
-                                     snapshot['name'])
-        try:
-            dst_nms.snapshot.destroy(dst_snapshot, '')
-        except nexenta.NexentaException as exc:
-            LOG.warning(_LW("Cannot delete temporary destination snapshot "
-                            "%(dst)s on NexentaStor Appliance: %(exc)s"),
-                        {'dst': dst_snapshot, 'exc': exc})
-
-        provider_location = '%(host)s:%(port)s,1 %(name)s 0' % {
-            'host': dst_host,
-            'port': iscsi_target_portal_port,
-            'name': self._get_target_name(volume['name'])
-        }
-
-        return True, {'provider_location': provider_location}
-
-    def create_snapshot(self, snapshot):
-        """Create snapshot of existing zvol on appliance.
-
-        :param snapshot: snapshot reference
-        """
-        self.nms.zvol.create_snapshot(
-            self._get_zvol_name(snapshot['volume_name']),
-            snapshot['name'], '')
-
-    def create_volume_from_snapshot(self, volume, snapshot):
-        """Create new volume from other's snapshot on appliance.
-
-        :param volume: reference of volume to be created
-        :param snapshot: reference of source snapshot
-        """
-        self.nms.zvol.clone(
-            '%s@%s' % (self._get_zvol_name(snapshot['volume_name']),
-                       snapshot['name']),
-            self._get_zvol_name(volume['name']))
-
-    def delete_snapshot(self, snapshot):
-        """Delete volume's snapshot on appliance.
-
-        :param snapshot: snapshot reference
-        """
-        volume_name = self._get_zvol_name(snapshot['volume_name'])
-        snapshot_name = '%s@%s' % (volume_name, snapshot['name'])
-        try:
-            self.nms.snapshot.destroy(snapshot_name, '')
-        except nexenta.NexentaException as exc:
-            if "does not exist" in exc.args[0]:
-                LOG.info(_LI('Snapshot %s does not exist, it seems it was '
-                             'already deleted.'), snapshot_name)
-                return
-            if "snapshot has dependent clones" in exc.args[0]:
-                raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
-            raise
-
-    def local_path(self, volume):
-        """Return local path to existing local volume.
-
-        We never have local volumes, so it raises NotImplementedError.
-
-        :raise: :py:exc:`NotImplementedError`
-        """
-        raise NotImplementedError
-
-    def _target_exists(self, target):
-        """Check if iSCSI target exist.
-
-        :param target: target name
-        :return: True if target exist, else False
-        """
-        targets = self.nms.stmf.list_targets()
-        if not targets:
-            return False
-        return target in self.nms.stmf.list_targets()
-
-    def _target_group_exists(self, target_group):
-        """Check if target group exist.
-
-        :param target_group: target group
-        :return: True if target group exist, else False
-        """
-        groups = self.nms.stmf.list_targetgroups()
-        if not groups:
-            return False
-        return target_group in groups
-
-    def _target_member_in_target_group(self, target_group, target_member):
-        """Check if target member in target group.
-
-        :param target_group: target group
-        :param target_member: target member
-        :return: True if target member in target group, else False
-        :raises: NexentaException if target group doesn't exist
-        """
-        members = self.nms.stmf.list_targetgroup_members(target_group)
-        if not members:
-            return False
-        return target_member in members
-
-    def _lu_exists(self, zvol_name):
-        """Check if LU exists on appliance.
-
-        :param zvol_name: Zvol name
-        :raises: NexentaException if zvol not exists
-        :return: True if LU exists, else False
-        """
-        try:
-            return bool(self.nms.scsidisk.lu_exists(zvol_name))
-        except nexenta.NexentaException as exc:
-            if 'does not exist' not in exc.args[0]:
-                raise
-            return False
-
-    def _is_lu_shared(self, zvol_name):
-        """Check if LU exists on appliance and shared.
-
-        :param zvol_name: Zvol name
-        :raises: NexentaException if Zvol not exist
-        :return: True if LU exists and shared, else False
-        """
-        try:
-            shared = self.nms.scsidisk.lu_shared(zvol_name) > 0
-        except nexenta.NexentaException as exc:
-            if 'does not exist for zvol' not in exc.args[0]:
-                raise  # Zvol does not exists
-            shared = False  # LU does not exist
-        return shared
-
-    def _is_volume_exported(self, volume):
-        """Check if volume exported.
-
-        :param volume: volume object
-        :return: True if volume exported, else False
-        """
-        zvol_name = self._get_zvol_name(volume['name'])
-        target_name = self._get_target_name(volume['name'])
-        target_group_name = self._get_target_group_name(volume['name'])
-        return (self._target_exists(target_name) and
-                self._target_group_exists(target_group_name) and
-                self._target_member_in_target_group(target_group_name,
-                                                    target_name) and
-                self._lu_exists(zvol_name) and
-                self._is_lu_shared(zvol_name))
-
-    def _get_provider_location(self, volume):
-        """Returns volume iscsiadm-formatted provider location string."""
-        return '%(host)s:%(port)s,1 %(name)s 0' % {
-            'host': self.nms_host,
-            'port': self.configuration.nexenta_iscsi_target_portal_port,
-            'name': self._get_target_name(volume['name'])
-        }
-
-    def _do_export(self, _ctx, volume, ensure=False):
-        """Do all steps to get zvol exported as LUN 0 at separate target.
-
-        :param volume: reference of volume to be exported
-        :param ensure: if True, ignore errors caused by already existing
-            resources
-        """
-        zvol_name = self._get_zvol_name(volume['name'])
-        target_name = self._get_target_name(volume['name'])
-        target_group_name = self._get_target_group_name(volume['name'])
-
-        if not self._target_exists(target_name):
-            try:
-                self.nms.iscsitarget.create_target({
-                    'target_name': target_name})
-            except nexenta.NexentaException as exc:
-                if ensure and 'already configured' in exc.args[0]:
-                    LOG.info(_LI('Ignored target creation error "%s" while '
-                                 'ensuring export'), exc)
-                else:
-                    raise
-        if not self._target_group_exists(target_group_name):
-            try:
-                self.nms.stmf.create_targetgroup(target_group_name)
-            except nexenta.NexentaException as exc:
-                if ((ensure and 'already exists' in exc.args[0]) or
-                        'target must be offline' in exc.args[0]):
-                    LOG.info(_LI('Ignored target group creation error "%s" '
-                                 'while ensuring export'), exc)
-                else:
-                    raise
-        if not self._target_member_in_target_group(target_group_name,
-                                                   target_name):
-            try:
-                self.nms.stmf.add_targetgroup_member(target_group_name,
-                                                     target_name)
-            except nexenta.NexentaException as exc:
-                if ((ensure and 'already exists' in exc.args[0]) or
-                        'target must be offline' in exc.args[0]):
-                    LOG.info(_LI('Ignored target group member addition error '
-                                 '"%s" while ensuring export'), exc)
-                else:
-                    raise
-        if not self._lu_exists(zvol_name):
-            try:
-                self.nms.scsidisk.create_lu(zvol_name, {})
-            except nexenta.NexentaException as exc:
-                if not ensure or 'in use' not in exc.args[0]:
-                    raise
-                LOG.info(_LI('Ignored LU creation error "%s" while ensuring '
-                             'export'), exc)
-        if not self._is_lu_shared(zvol_name):
-            try:
-                self.nms.scsidisk.add_lun_mapping_entry(zvol_name, {
-                    'target_group': target_group_name})
-            except nexenta.NexentaException as exc:
-                if not ensure or 'view entry exists' not in exc.args[0]:
-                    raise
-                LOG.info(_LI('Ignored LUN mapping entry addition error "%s" '
-                             'while ensuring export'), exc)
-
-    def create_export(self, _ctx, volume):
-        """Create new export for zvol.
-
-        :param volume: reference of volume to be exported
-        :return: iscsiadm-formatted provider location string
-        """
-        self._do_export(_ctx, volume, ensure=False)
-        return {'provider_location': self._get_provider_location(volume)}
-
-    def ensure_export(self, _ctx, volume):
-        """Recreate parts of export if necessary.
-
-        :param volume: reference of volume to be exported
-        """
-        self._do_export(_ctx, volume, ensure=True)
-
-    def remove_export(self, _ctx, volume):
-        """Destroy all resources created to export zvol.
-
-        :param volume: reference of volume to be unexported
-        """
-        zvol_name = self._get_zvol_name(volume['name'])
-        target_name = self._get_target_name(volume['name'])
-        target_group_name = self._get_target_group_name(volume['name'])
-        self.nms.scsidisk.delete_lu(zvol_name)
-
-        try:
-            self.nms.stmf.destroy_targetgroup(target_group_name)
-        except nexenta.NexentaException as exc:
-            # We assume that target group is already gone
-            LOG.warn(_LW('Got error trying to destroy target group'
-                         ' %(target_group)s, assuming it is '
-                         'already gone: %(exc)s'),
-                     {'target_group': target_group_name, 'exc': exc})
-        try:
-            self.nms.iscsitarget.delete_target(target_name)
-        except nexenta.NexentaException as exc:
-            # We assume that target is gone as well
-            LOG.warn(_LW('Got error trying to delete target %(target)s,'
-                         ' assuming it is already gone: %(exc)s'),
-                     {'target': target_name, 'exc': exc})
-
-    def get_volume_stats(self, refresh=False):
-        """Get volume stats.
-
-        If 'refresh' is True, run update the stats first.
-        """
-        if refresh:
-            self._update_volume_stats()
-
-        return self._stats
-
-    def _update_volume_stats(self):
-        """Retrieve stats info for NexentaStor appliance."""
-        LOG.debug('Updating volume stats')
-
-        stats = self.nms.volume.get_child_props(
-            self.configuration.nexenta_volume, 'health|size|used|available')
-
-        total_amount = utils.str2gib_size(stats['size'])
-        free_amount = utils.str2gib_size(stats['available'])
-
-        location_info = '%(driver)s:%(host)s:%(volume)s' % {
-            'driver': self.__class__.__name__,
-            'host': self.nms_host,
-            'volume': self.volume
-        }
-
-        self._stats = {
-            'vendor_name': 'Nexenta',
-            'driver_version': self.VERSION,
-            'storage_protocol': 'iSCSI',
-            'total_capacity_gb': total_amount,
-            'free_capacity_gb': free_amount,
-            'reserved_percentage': 0,
-            'QoS_support': False,
-            'volume_backend_name': self.backend_name,
-            'location_info': location_info,
-            'iscsi_target_portal_port': self.iscsi_target_portal_port,
-            'nms_url': self.nms.url
-        }
diff --git a/cinder/volume/drivers/nexenta/jsonrpc.py b/cinder/volume/drivers/nexenta/jsonrpc.py
deleted file mode 100644 (file)
index 49a3067..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright 2011 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta.jsonrpc` -- Nexenta-specific JSON RPC client
-=====================================================================
-
-.. automodule:: nexenta.jsonrpc
-.. moduleauthor:: Yuriy Taraday <yorik.sar@gmail.com>
-.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
-"""
-
-import urllib2
-
-from oslo_log import log as logging
-from oslo_serialization import jsonutils
-
-from cinder.i18n import _, _LE, _LI
-from cinder.volume.drivers import nexenta
-
-LOG = logging.getLogger(__name__)
-
-
-class NexentaJSONException(nexenta.NexentaException):
-    pass
-
-
-class NexentaJSONProxy(object):
-
-    def __init__(self, scheme, host, port, path, user, password, auto=False,
-                 obj=None, method=None):
-        self.scheme = scheme.lower()
-        self.host = host
-        self.port = port
-        self.path = path
-        self.user = user
-        self.password = password
-        self.auto = auto
-        self.obj = obj
-        self.method = method
-
-    def __getattr__(self, name):
-        if not self.obj:
-            obj, method = name, None
-        elif not self.method:
-            obj, method = self.obj, name
-        else:
-            obj, method = '%s.%s' % (self.obj, self.method), name
-        return NexentaJSONProxy(self.scheme, self.host, self.port, self.path,
-                                self.user, self.password, self.auto, obj,
-                                method)
-
-    @property
-    def url(self):
-        return '%s://%s:%s%s' % (self.scheme, self.host, self.port, self.path)
-
-    def __hash__(self):
-        return self.url.__hash__()
-
-    def __repr__(self):
-        return 'NMS proxy: %s' % self.url
-
-    def __call__(self, *args):
-        data = jsonutils.dumps({
-            'object': self.obj,
-            'method': self.method,
-            'params': args
-        })
-        auth = ('%s:%s' % (self.user, self.password)).encode('base64')[:-1]
-        headers = {
-            'Content-Type': 'application/json',
-            'Authorization': 'Basic %s' % auth
-        }
-        LOG.debug('Sending JSON data: %s', data)
-        request = urllib2.Request(self.url, data, headers)
-        response_obj = urllib2.urlopen(request)
-        if response_obj.info().status == 'EOF in headers':
-            if not self.auto or self.scheme != 'http':
-                LOG.error(_LE('No headers in server response'))
-                raise NexentaJSONException(_('Bad response from server'))
-            LOG.info(_LI('Auto switching to HTTPS connection to %s'), self.url)
-            self.scheme = 'https'
-            request = urllib2.Request(self.url, data, headers)
-            response_obj = urllib2.urlopen(request)
-
-        response_data = response_obj.read()
-        LOG.debug('Got response: %s', response_data)
-        response = jsonutils.loads(response_data)
-        if response.get('error') is not None:
-            raise NexentaJSONException(response['error'].get('message', ''))
-        return response.get('result')
diff --git a/cinder/volume/drivers/nexenta/nfs.py b/cinder/volume/drivers/nexenta/nfs.py
deleted file mode 100644 (file)
index 6fe5722..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-# Copyright 2013 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta.nfs` -- Driver to store volumes on NexentaStor Appliance.
-=======================================================================
-
-.. automodule:: nexenta.nfs
-.. moduleauthor:: Mikhail Khodos <hodosmb@gmail.com>
-.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
-"""
-
-import hashlib
-import os
-import re
-
-from oslo_log import log as logging
-from oslo_utils import units
-
-from cinder import context
-from cinder import db
-from cinder import exception
-from cinder.i18n import _, _LE, _LI, _LW
-from cinder.volume.drivers import nexenta
-from cinder.volume.drivers.nexenta import jsonrpc
-from cinder.volume.drivers.nexenta import options
-from cinder.volume.drivers.nexenta import utils
-from cinder.volume.drivers import nfs
-
-VERSION = '1.1.3'
-LOG = logging.getLogger(__name__)
-
-
-class NexentaNfsDriver(nfs.NfsDriver):  # pylint: disable=R0921
-    """Executes volume driver commands on Nexenta Appliance.
-
-    Version history:
-        1.0.0 - Initial driver version.
-        1.1.0 - Auto sharing for enclosing folder.
-        1.1.1 - Added caching for NexentaStor appliance 'volroot' value.
-        1.1.2 - Ignore "folder does not exist" error in delete_volume and
-                delete_snapshot method.
-        1.1.3 - Redefined volume_backend_name attribute inherited from
-                RemoteFsDriver.
-    """
-
-    driver_prefix = 'nexenta'
-    volume_backend_name = 'NexentaNfsDriver'
-    VERSION = VERSION
-
-    def __init__(self, *args, **kwargs):
-        super(NexentaNfsDriver, self).__init__(*args, **kwargs)
-        if self.configuration:
-            self.configuration.append_config_values(
-                options.NEXENTA_NFS_OPTIONS)
-        conf = self.configuration
-        self.nms_cache_volroot = conf.nexenta_nms_cache_volroot
-        self._nms2volroot = {}
-        self.share2nms = {}
-
-    def do_setup(self, context):
-        super(NexentaNfsDriver, self).do_setup(context)
-        self._load_shares_config(getattr(self.configuration,
-                                         self.driver_prefix +
-                                         '_shares_config'))
-
-    def check_for_setup_error(self):
-        """Verify that the volume for our folder exists.
-
-        :raise: :py:exc:`LookupError`
-        """
-        if self.share2nms:
-            for nfs_share in self.share2nms:
-                nms = self.share2nms[nfs_share]
-                volume_name, dataset = self._get_share_datasets(nfs_share)
-                if not nms.volume.object_exists(volume_name):
-                    raise LookupError(_("Volume %s does not exist in Nexenta "
-                                        "Store appliance"), volume_name)
-                folder = '%s/%s' % (volume_name, dataset)
-                if not nms.folder.object_exists(folder):
-                    raise LookupError(_("Folder %s does not exist in Nexenta "
-                                        "Store appliance"), folder)
-                self._share_folder(nms, volume_name, dataset)
-
-    def initialize_connection(self, volume, connector):
-        """Allow connection to connector and return connection info.
-
-        :param volume: volume reference
-        :param connector: connector reference
-        """
-        export = '%s/%s' % (volume['provider_location'], volume['name'])
-        data = {'export': export, 'name': 'volume'}
-        if volume['provider_location'] in self.shares:
-            data['options'] = self.shares[volume['provider_location']]
-        return {
-            'driver_volume_type': self.driver_volume_type,
-            'data': data
-        }
-
-    def _do_create_volume(self, volume):
-        nfs_share = volume['provider_location']
-        nms = self.share2nms[nfs_share]
-
-        vol, dataset = self._get_share_datasets(nfs_share)
-        folder = '%s/%s' % (dataset, volume['name'])
-        LOG.debug('Creating folder on Nexenta Store %s', folder)
-        nms.folder.create_with_props(
-            vol, folder,
-            {'compression': self.configuration.nexenta_volume_compression}
-        )
-
-        volume_path = self.remote_path(volume)
-        volume_size = volume['size']
-        try:
-            self._share_folder(nms, vol, folder)
-
-            if getattr(self.configuration,
-                       self.driver_prefix + '_sparsed_volumes'):
-                self._create_sparsed_file(nms, volume_path, volume_size)
-            else:
-                compression = nms.folder.get('compression')
-                if compression != 'off':
-                    # Disable compression, because otherwise will not use space
-                    # on disk.
-                    nms.folder.set('compression', 'off')
-                try:
-                    self._create_regular_file(nms, volume_path, volume_size)
-                finally:
-                    if compression != 'off':
-                        # Backup default compression value if it was changed.
-                        nms.folder.set('compression', compression)
-
-            self._set_rw_permissions_for_all(nms, volume_path)
-        except nexenta.NexentaException as exc:
-            try:
-                nms.folder.destroy('%s/%s' % (vol, folder))
-            except nexenta.NexentaException:
-                LOG.warning(_LW("Cannot destroy created folder: "
-                                "%(vol)s/%(folder)s"),
-                            {'vol': vol, 'folder': folder})
-            raise exc
-
-    def create_volume_from_snapshot(self, volume, snapshot):
-        """Create new volume from other's snapshot on appliance.
-
-        :param volume: reference of volume to be created
-        :param snapshot: reference of source snapshot
-        """
-        self._ensure_shares_mounted()
-
-        snapshot_vol = self._get_snapshot_volume(snapshot)
-        nfs_share = snapshot_vol['provider_location']
-        volume['provider_location'] = nfs_share
-        nms = self.share2nms[nfs_share]
-
-        vol, dataset = self._get_share_datasets(nfs_share)
-        snapshot_name = '%s/%s/%s@%s' % (vol, dataset, snapshot['volume_name'],
-                                         snapshot['name'])
-        folder = '%s/%s' % (dataset, volume['name'])
-        nms.folder.clone(snapshot_name, '%s/%s' % (vol, folder))
-
-        try:
-            self._share_folder(nms, vol, folder)
-        except nexenta.NexentaException:
-            try:
-                nms.folder.destroy('%s/%s' % (vol, folder), '')
-            except nexenta.NexentaException:
-                LOG.warning(_LW("Cannot destroy cloned folder: "
-                                "%(vol)s/%(folder)s"),
-                            {'vol': vol, 'folder': folder})
-            raise
-
-        return {'provider_location': volume['provider_location']}
-
-    def create_cloned_volume(self, volume, src_vref):
-        """Creates a clone of the specified volume.
-
-        :param volume: new volume reference
-        :param src_vref: source volume reference
-        """
-        LOG.info(_LI('Creating clone of volume: %s'), src_vref['id'])
-        snapshot = {'volume_name': src_vref['name'],
-                    'volume_id': src_vref['id'],
-                    'name': self._get_clone_snapshot_name(volume)}
-        # We don't delete this snapshot, because this snapshot will be origin
-        # of new volume. This snapshot will be automatically promoted by NMS
-        # when user will delete its origin.
-        self.create_snapshot(snapshot)
-        try:
-            return self.create_volume_from_snapshot(volume, snapshot)
-        except nexenta.NexentaException:
-            LOG.error(_LE('Volume creation failed, deleting created snapshot '
-                          '%(volume_name)s@%(name)s'), snapshot)
-            try:
-                self.delete_snapshot(snapshot)
-            except (nexenta.NexentaException, exception.SnapshotIsBusy):
-                LOG.warning(_LW('Failed to delete zfs snapshot '
-                                '%(volume_name)s@%(name)s'), snapshot)
-            raise
-
-    def delete_volume(self, volume):
-        """Deletes a logical volume.
-
-        :param volume: volume reference
-        """
-        super(NexentaNfsDriver, self).delete_volume(volume)
-
-        nfs_share = volume.get('provider_location')
-
-        if nfs_share:
-            nms = self.share2nms[nfs_share]
-            vol, parent_folder = self._get_share_datasets(nfs_share)
-            folder = '%s/%s/%s' % (vol, parent_folder, volume['name'])
-            props = nms.folder.get_child_props(folder, 'origin') or {}
-            try:
-                nms.folder.destroy(folder, '-r')
-            except nexenta.NexentaException as exc:
-                if 'does not exist' in exc.args[0]:
-                    LOG.info(_LI('Folder %s does not exist, it was '
-                                 'already deleted.'), folder)
-                    return
-                raise
-            origin = props.get('origin')
-            if origin and self._is_clone_snapshot_name(origin):
-                try:
-                    nms.snapshot.destroy(origin, '')
-                except nexenta.NexentaException as exc:
-                    if 'does not exist' in exc.args[0]:
-                        LOG.info(_LI('Snapshot %s does not exist, it was '
-                                     'already deleted.'), origin)
-                        return
-                    raise
-
-    def create_snapshot(self, snapshot):
-        """Creates a snapshot.
-
-        :param snapshot: snapshot reference
-        """
-        volume = self._get_snapshot_volume(snapshot)
-        nfs_share = volume['provider_location']
-        nms = self.share2nms[nfs_share]
-        vol, dataset = self._get_share_datasets(nfs_share)
-        folder = '%s/%s/%s' % (vol, dataset, volume['name'])
-        nms.folder.create_snapshot(folder, snapshot['name'], '-r')
-
-    def delete_snapshot(self, snapshot):
-        """Deletes a snapshot.
-
-        :param snapshot: snapshot reference
-        """
-        volume = self._get_snapshot_volume(snapshot)
-        nfs_share = volume['provider_location']
-        nms = self.share2nms[nfs_share]
-        vol, dataset = self._get_share_datasets(nfs_share)
-        folder = '%s/%s/%s' % (vol, dataset, volume['name'])
-        try:
-            nms.snapshot.destroy('%s@%s' % (folder, snapshot['name']), '')
-        except nexenta.NexentaException as exc:
-            if 'does not exist' in exc.args[0]:
-                LOG.info(_LI('Snapshot %s does not exist, it was '
-                             'already deleted.'), '%s@%s' % (folder, snapshot))
-                return
-            raise
-
-    def _create_sparsed_file(self, nms, path, size):
-        """Creates file with 0 disk usage.
-
-        :param nms: nms object
-        :param path: path to new file
-        :param size: size of file
-        """
-        nms.appliance.execute(
-            'truncate --size %(size)dG %(path)s' % {
-                'path': path,
-                'size': size
-            }
-        )
-
-    def _create_regular_file(self, nms, path, size):
-        """Creates regular file of given size.
-        Takes a lot of time for large files.
-
-        :param nms: nms object
-        :param path: path to new file
-        :param size: size of file
-        """
-        block_size_mb = 1
-        block_count = size * units.Gi / (block_size_mb * units.Mi)
-
-        LOG.info(_LI('Creating regular file: %s.'
-                     'This may take some time.') % path)
-
-        nms.appliance.execute(
-            'dd if=/dev/zero of=%(path)s bs=%(bs)dM count=%(count)d' % {
-                'path': path,
-                'bs': block_size_mb,
-                'count': block_count
-            }
-        )
-
-        LOG.info(_LI('Regular file: %s created.') % path)
-
-    def _set_rw_permissions_for_all(self, nms, path):
-        """Sets 666 permissions for the path.
-
-        :param nms: nms object
-        :param path: path to file
-        """
-        nms.appliance.execute('chmod ugo+rw %s' % path)
-
-    def local_path(self, volume):
-        """Get volume path (mounted locally fs path) for given volume.
-
-        :param volume: volume reference
-        """
-        nfs_share = volume['provider_location']
-        return os.path.join(self._get_mount_point_for_share(nfs_share),
-                            volume['name'], 'volume')
-
-    def _get_mount_point_for_share(self, nfs_share):
-        """Returns path to mount point NFS share.
-
-        :param nfs_share: example 172.18.194.100:/var/nfs
-        """
-        return os.path.join(self.configuration.nexenta_mount_point_base,
-                            hashlib.md5(nfs_share).hexdigest())
-
-    def remote_path(self, volume):
-        """Get volume path (mounted remotely fs path) for given volume.
-
-        :param volume: volume reference
-        """
-        nfs_share = volume['provider_location']
-        share = nfs_share.split(':')[1].rstrip('/')
-        return '%s/%s/volume' % (share, volume['name'])
-
-    def _share_folder(self, nms, volume, folder):
-        """Share NFS folder on NexentaStor Appliance.
-
-        :param nms: nms object
-        :param volume: volume name
-        :param folder: folder name
-        """
-        path = '%s/%s' % (volume, folder.lstrip('/'))
-        share_opts = {
-            'read_write': '*',
-            'read_only': '',
-            'root': 'nobody',
-            'extra_options': 'anon=0',
-            'recursive': 'true',
-            'anonymous_rw': 'true',
-        }
-        LOG.debug('Sharing folder %s on Nexenta Store', folder)
-        nms.netstorsvc.share_folder('svc:/network/nfs/server:default', path,
-                                    share_opts)
-
-    def _load_shares_config(self, share_file):
-        self.shares = {}
-        self.share2nms = {}
-
-        for share in self._read_config_file(share_file):
-            # A configuration line may be either:
-            # host:/share_name  http://user:pass@host:[port]/
-            # or
-            # host:/share_name  http://user:pass@host:[port]/
-            #    -o options=123,rw --other
-            if not share.strip():
-                continue
-            if share.startswith('#'):
-                continue
-
-            share_info = re.split(r'\s+', share, 2)
-
-            share_address = share_info[0].strip().decode('unicode_escape')
-            nms_url = share_info[1].strip()
-            share_opts = share_info[2].strip() if len(share_info) > 2 else None
-
-            if not re.match(r'.+:/.+', share_address):
-                LOG.warn("Share %s ignored due to invalid format.  Must be of "
-                         "form address:/export." % share_address)
-                continue
-
-            self.shares[share_address] = share_opts
-            self.share2nms[share_address] = self._get_nms_for_url(nms_url)
-
-        LOG.debug('Shares loaded: %s' % self.shares)
-
-    def _get_capacity_info(self, nfs_share):
-        """Calculate available space on the NFS share.
-
-        :param nfs_share: example 172.18.194.100:/var/nfs
-        """
-        nms = self.share2nms[nfs_share]
-        ns_volume, ns_folder = self._get_share_datasets(nfs_share)
-        folder_props = nms.folder.get_child_props('%s/%s' % (ns_volume,
-                                                             ns_folder), '')
-        free = utils.str2size(folder_props['available'])
-        allocated = utils.str2size(folder_props['used'])
-        return free + allocated, free, allocated
-
-    def _get_nms_for_url(self, url):
-        """Returns initialized nms object for url."""
-        auto, scheme, user, password, host, port, path =\
-            utils.parse_nms_url(url)
-        return jsonrpc.NexentaJSONProxy(scheme, host, port, path, user,
-                                        password, auto=auto)
-
-    def _get_snapshot_volume(self, snapshot):
-        ctxt = context.get_admin_context()
-        return db.volume_get(ctxt, snapshot['volume_id'])
-
-    def _get_volroot(self, nms):
-        """Returns volroot property value from NexentaStor appliance."""
-        if not self.nms_cache_volroot:
-            return nms.server.get_prop('volroot')
-        if nms not in self._nms2volroot:
-            self._nms2volroot[nms] = nms.server.get_prop('volroot')
-        return self._nms2volroot[nms]
-
-    def _get_share_datasets(self, nfs_share):
-        nms = self.share2nms[nfs_share]
-        volroot = self._get_volroot(nms)
-        path = nfs_share.split(':')[1][len(volroot):].strip('/')
-        volume_name = path.split('/')[0]
-        folder_name = '/'.join(path.split('/')[1:])
-        return volume_name, folder_name
-
-    def _get_clone_snapshot_name(self, volume):
-        """Return name for snapshot that will be used to clone the volume."""
-        return 'cinder-clone-snapshot-%(id)s' % volume
-
-    def _is_clone_snapshot_name(self, snapshot):
-        """Check if snapshot is created for cloning."""
-        name = snapshot.split('@')[-1]
-        return name.startswith('cinder-clone-snapshot-')
diff --git a/cinder/volume/drivers/nexenta/options.py b/cinder/volume/drivers/nexenta/options.py
deleted file mode 100644 (file)
index 9f72bb0..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright 2013 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta.options` -- Contains configuration options for Nexenta drivers.
-=============================================================================
-
-.. automodule:: nexenta.options
-.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
-.. moduleauthor:: Yuriy Taraday <yorik.sar@gmail.com>
-"""
-
-from oslo_config import cfg
-
-
-NEXENTA_CONNECTION_OPTIONS = [
-    cfg.StrOpt('nexenta_host',
-               default='',
-               help='IP address of Nexenta SA'),
-    cfg.IntOpt('nexenta_rest_port',
-               default=2000,
-               help='HTTP port to connect to Nexenta REST API server'),
-    cfg.StrOpt('nexenta_rest_protocol',
-               default='auto',
-               choices=['http', 'https', 'auto'],
-               help='Use http or https for REST connection (default auto)'),
-    cfg.StrOpt('nexenta_user',
-               default='admin',
-               help='User name to connect to Nexenta SA'),
-    cfg.StrOpt('nexenta_password',
-               default='nexenta',
-               help='Password to connect to Nexenta SA',
-               secret=True),
-]
-
-NEXENTA_ISCSI_OPTIONS = [
-    cfg.IntOpt('nexenta_iscsi_target_portal_port',
-               default=3260,
-               help='Nexenta target portal port'),
-    cfg.StrOpt('nexenta_volume',
-               default='cinder',
-               help='SA Pool that holds all volumes'),
-    cfg.StrOpt('nexenta_target_prefix',
-               default='iqn.1986-03.com.sun:02:cinder-',
-               help='IQN prefix for iSCSI targets'),
-    cfg.StrOpt('nexenta_target_group_prefix',
-               default='cinder/',
-               help='Prefix for iSCSI target groups on SA'),
-]
-
-NEXENTA_NFS_OPTIONS = [
-    cfg.StrOpt('nexenta_shares_config',
-               default='/etc/cinder/nfs_shares',
-               help='File with the list of available nfs shares'),
-    cfg.StrOpt('nexenta_mount_point_base',
-               default='$state_path/mnt',
-               help='Base directory that contains NFS share mount points'),
-    cfg.BoolOpt('nexenta_sparsed_volumes',
-                default=True,
-                help='Enables or disables the creation of volumes as '
-                     'sparsed files that take no space. If disabled '
-                     '(False), volume is created as a regular file, '
-                     'which takes a long time.'),
-    cfg.StrOpt('nexenta_volume_compression',
-               default='on',
-               choices=['on', 'off'],
-               help='Default compression value for new ZFS folders.'),
-    cfg.BoolOpt('nexenta_nms_cache_volroot',
-                default=True,
-                help=('If set True cache NexentaStor appliance volroot option '
-                      'value.'))
-]
-
-NEXENTA_VOLUME_OPTIONS = [
-    cfg.StrOpt('nexenta_blocksize',
-               default='',
-               help='Block size for volumes (default=blank means 8KB)'),
-    cfg.BoolOpt('nexenta_sparse',
-                default=False,
-                help='Enables or disables the creation of sparse volumes'),
-]
-
-NEXENTA_RRMGR_OPTIONS = [
-    cfg.IntOpt('nexenta_rrmgr_compression',
-               default=0,
-               help=('Enable stream compression, level 1..9. 1 - gives best '
-                     'speed; 9 - gives best compression.')),
-    cfg.IntOpt('nexenta_rrmgr_tcp_buf_size',
-               default=4096,
-               help='TCP Buffer size in KiloBytes.'),
-    cfg.IntOpt('nexenta_rrmgr_connections',
-               default=2,
-               help='Number of TCP connections.'),
-]
-
-CONF = cfg.CONF
-CONF.register_opts(NEXENTA_CONNECTION_OPTIONS)
-CONF.register_opts(NEXENTA_ISCSI_OPTIONS)
-CONF.register_opts(NEXENTA_VOLUME_OPTIONS)
-CONF.register_opts(NEXENTA_NFS_OPTIONS)
-CONF.register_opts(NEXENTA_RRMGR_OPTIONS)
diff --git a/cinder/volume/drivers/nexenta/utils.py b/cinder/volume/drivers/nexenta/utils.py
deleted file mode 100644 (file)
index 93a636e..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2013 Nexenta Systems, Inc.
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-"""
-:mod:`nexenta.utils` -- Nexenta-specific utils functions.
-=========================================================
-
-.. automodule:: nexenta.utils
-.. moduleauthor:: Victor Rodionov <victor.rodionov@nexenta.com>
-.. moduleauthor:: Mikhail Khodos <mikhail.khodos@nexenta.com>
-"""
-
-import re
-
-from oslo_utils import units
-import six.moves.urllib.parse as urlparse
-
-from cinder.i18n import _
-
-
-def str2size(s, scale=1024):
-    """Convert size-string.
-
-    String format: <value>[:space:]<B | K | M | ...> to bytes.
-
-    :param s: size-string
-    :param scale: base size
-    """
-    if not s:
-        return 0
-
-    if isinstance(s, (int, long)):
-        return s
-
-    match = re.match(r'^([\.\d]+)\s*([BbKkMmGgTtPpEeZzYy]?)', s)
-    if match is None:
-        raise ValueError(_('Invalid value: "%s"') % s)
-
-    groups = match.groups()
-    value = float(groups[0])
-    suffix = len(groups) > 1 and groups[1].upper() or 'B'
-
-    types = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
-    for i, t in enumerate(types):
-        if suffix == t:
-            return int(value * pow(scale, i))
-
-
-def str2gib_size(s):
-    """Covert size-string to size in gigabytes."""
-    size_in_bytes = str2size(s)
-    return size_in_bytes / units.Gi
-
-
-def get_rrmgr_cmd(src, dst, compression=None, tcp_buf_size=None,
-                  connections=None):
-    """Returns rrmgr command for source and destination."""
-    cmd = ['rrmgr', '-s', 'zfs']
-    if compression:
-        cmd.extend(['-c', '%s' % str(compression)])
-    cmd.append('-q')
-    cmd.append('-e')
-    if tcp_buf_size:
-        cmd.extend(['-w', str(tcp_buf_size)])
-    if connections:
-        cmd.extend(['-n', str(connections)])
-    cmd.extend([src, dst])
-    return ' '.join(cmd)
-
-
-def parse_nms_url(url):
-    """Parse NMS url into normalized parts like scheme, user, host and others.
-
-    Example NMS URL:
-        auto://admin:nexenta@192.168.1.1:2000/
-
-    NMS URL parts:
-        auto                True if url starts with auto://, protocol will be
-                            automatically switched to https if http not
-                            supported;
-        scheme (auto)       connection protocol (http or https);
-        user (admin)        NMS user;
-        password (nexenta)  NMS password;
-        host (192.168.1.1)  NMS host;
-        port (2000)         NMS port.
-
-    :param url: url string
-    :return: tuple (auto, scheme, user, password, host, port, path)
-    """
-    pr = urlparse.urlparse(url)
-    scheme = pr.scheme
-    auto = scheme == 'auto'
-    if auto:
-        scheme = 'http'
-    user = 'admin'
-    password = 'nexenta'
-    if '@' not in pr.netloc:
-        host_and_port = pr.netloc
-    else:
-        user_and_password, host_and_port = pr.netloc.split('@', 1)
-        if ':' in user_and_password:
-            user, password = user_and_password.split(':')
-        else:
-            user = user_and_password
-    if ':' in host_and_port:
-        host, port = host_and_port.split(':', 1)
-    else:
-        host, port = host_and_port, '2000'
-    return auto, scheme, user, password, host, port, '/rest/nms/'
-
-
-def get_migrate_snapshot_name(volume):
-    """Return name for snapshot that will be used to migrate the volume."""
-    return 'cinder-migrate-snapshot-%(id)s' % volume