components/openstack/cinder/files/zfssa/zfssarest.py
branchs11u2-sru
changeset 4156 4b1def16fe9b
parent 4146 097063f324c0
child 4157 92532a6159e7
--- a/components/openstack/cinder/files/zfssa/zfssarest.py	Thu Apr 16 01:36:32 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,614 +0,0 @@
-# Copyright (c) 2014, Oracle and/or its affiliates. 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.
-"""
-ZFS Storage Appliance Proxy
-"""
-import json
-import socket
-
-from cinder import exception
-from cinder.openstack.common import log
-
-from cinder.volume.drivers.zfssa import restclient
-
-LOG = log.getLogger(__name__)
-
-
-#pylint: disable=R0913
-#pylint: disable=R0904
-class ZFSSAApi(object):
-    """ZFSSA API proxy class"""
-    def __init__(self, host):
-        self.host = host
-        self.url = "https://" + self.host + ":215"
-        self.rclient = restclient.RestClientURL(self.url)
-
-    def __del__(self):
-        if self.rclient and self.rclient.islogin():
-            self.rclient.logout()
-
-    def _is_pool_owned(self, pdata):
-        """returns True if the pool's owner is the
-           same as the host.
-        """
-        svc = '/api/system/v1/version'
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error getting version: '
-                               'svc: %(svc)s.'
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'svc': svc,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-        vdata = json.loads(ret.data)
-        return vdata['version']['asn'] == pdata['pool']['asn'] and \
-            vdata['version']['nodename'] == pdata['pool']['owner']
-
-    def login(self, auth_str):
-        """Login to the appliance"""
-        if self.rclient:
-            self.rclient.login(auth_str)
-
-    def get_pool_stats(self, pool):
-        """Get space_available and used properties of a pool
-           returns (avail, used)
-        """
-        svc = '/api/storage/v1/pools/' + pool
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Getting Pool Stats: '
-                               'Pool: %(pool)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'pool': pool,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.InvalidVolume(reason=exception_msg)
-
-        val = json.loads(ret.data)
-
-        if not self._is_pool_owned(val):
-            exception_msg = (_('Error Pool ownership: '
-                               'Pool %(pool)s is not owned '
-                               'by %(host)s.')
-                             % {'pool': pool,
-                                'host': self.host})
-            LOG.error(exception_msg)
-            raise exception.InstanceNotFound(instance_id=pool)
-
-        avail = val['pool']['usage']['available']
-        used = val['pool']['usage']['used']
-
-        return (avail, used)
-
-    def create_project(self, pool, project, compression=None, logbias=None):
-        """Create a project on a pool
-           Check first whether the pool exists.
-        """
-        self.verify_pool(pool)
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + project
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svc = '/api/storage/v1/pools/' + pool + '/projects'
-            arg = {
-                'name': project
-            }
-            if compression and compression != '':
-                arg.update({'compression': compression})
-            if logbias and logbias != '':
-                arg.update({'logbias': logbias})
-
-            ret = self.rclient.post(svc, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Creating Project: '
-                                   '%(project)s on '
-                                   'Pool: %(pool)s '
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'project': project,
-                                    'pool': pool,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def create_initiator(self, initiator, alias, chapuser=None,
-                         chapsecret=None):
-        """Create an iSCSI initiator"""
-
-        svc = '/api/san/v1/iscsi/initiators/alias=' + alias
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svc = '/api/san/v1/iscsi/initiators'
-            arg = {
-                'initiator': initiator,
-                'alias': alias
-            }
-            if chapuser and chapuser != '' and chapsecret and chapsecret != '':
-                arg.update({'chapuser': chapuser,
-                            'chapsecret': chapsecret})
-
-            ret = self.rclient.post(svc, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Creating Initator: '
-                                   '%(initiator)s on '
-                                   'Alias: %(alias)s '
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'initiator': initiator,
-                                    'alias': alias,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def add_to_initiatorgroup(self, initiator, initiatorgroup):
-        """Add an iSCSI initiator to initiatorgroup"""
-        svc = '/api/san/v1/iscsi/initiator-groups/' + initiatorgroup
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svc = '/api/san/v1/iscsi/initiator-groups'
-            arg = {
-                'name': initiatorgroup,
-                'initiators': [initiator]
-            }
-            ret = self.rclient.post(svc, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Adding Initator: '
-                                   '%(initiator)s on group'
-                                   'InitiatorGroup: %(initiatorgroup)s '
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'initiator': initiator,
-                                    'initiatorgroup': initiatorgroup,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-        else:
-            svc = '/api/san/v1/iscsi/initiator-groups/' + initiatorgroup
-            arg = {
-                'initiators': [initiator]
-            }
-            ret = self.rclient.put(svc, arg)
-            if ret.status != restclient.Status.ACCEPTED:
-                exception_msg = (_('Error Adding Initator: '
-                                   '%(initiator)s on group'
-                                   'InitiatorGroup: %(initiatorgroup)s '
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'initiator': initiator,
-                                    'initiatorgroup': initiatorgroup,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def create_target(self, alias, interfaces=None, tchapuser=None,
-                      tchapsecret=None):
-        """Create an iSCSI target
-           interfaces: an array with network interfaces
-           tchapuser, tchapsecret: target's chapuser and chapsecret
-           returns target iqn
-        """
-        svc = '/api/san/v1/iscsi/targets/alias=' + alias
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svc = '/api/san/v1/iscsi/targets'
-            arg = {
-                'alias': alias
-            }
-
-            if tchapuser and tchapuser != '' and tchapsecret and \
-               tchapsecret != '':
-                arg.update({'targetchapuser': tchapuser,
-                            'targetchapsecret': tchapsecret,
-                            'auth': 'chap'})
-
-            if interfaces is not None and len(interfaces) > 0:
-                arg.update({'interfaces': interfaces})
-
-            ret = self.rclient.post(svc, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Creating Target: '
-                                   '%(alias)s'
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'alias': alias,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-        val = json.loads(ret.data)
-        return val['target']['iqn']
-
-    def get_target(self, alias):
-        """Get an iSCSI target iqn"""
-        svc = '/api/san/v1/iscsi/targets/alias=' + alias
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Getting Target: '
-                               '%(alias)s'
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s .')
-                             % {'alias': alias,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-        val = json.loads(ret.data)
-        return val['target']['iqn']
-
-    def add_to_targetgroup(self, iqn, targetgroup):
-        """Add an iSCSI target to targetgroup"""
-        svc = '/api/san/v1/iscsi/target-groups/' + targetgroup
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svccrt = '/api/san/v1/iscsi/target-groups'
-            arg = {
-                'name': targetgroup,
-                'targets': [iqn]
-            }
-
-            ret = self.rclient.post(svccrt, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Creating TargetGroup: '
-                                   '%(targetgroup)s with'
-                                   'IQN: %(iqn)s'
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s .')
-                                 % {'targetgroup': targetgroup,
-                                    'iqn': iqn,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-            return
-
-        arg = {
-            'targets': [iqn]
-        }
-
-        ret = self.rclient.put(svc, arg)
-        if ret.status != restclient.Status.ACCEPTED:
-            exception_msg = (_('Error Adding to TargetGroup: '
-                               '%(targetgroup)s with'
-                               'IQN: %(iqn)s'
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'targetgroup': targetgroup,
-                                'iqn': iqn,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def verify_pool(self, pool):
-        """Checks whether pool exists"""
-        svc = '/api/storage/v1/pools/' + pool
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Verifying Pool: '
-                               '%(pool)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'pool': pool,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def verify_project(self, pool, project):
-        """Checks whether project exists"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + project
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Verifying '
-                               'Project: %(project)s on '
-                               'Pool: %(pool)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'project': project,
-                                'pool': pool,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def verify_initiator(self, iqn):
-        """Check whether initiator iqn exists"""
-        svc = '/api/san/v1/iscsi/initiators/' + iqn
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Verifying '
-                               'Initiator: %(iqn)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'initiator': iqn,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def verify_target(self, alias):
-        """Check whether target alias exists."""
-        svc = '/api/san/v1/iscsi/targets/alias=' + alias
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Verifying '
-                               'Target: %(alias)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'alias': alias,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def create_lun(self, pool, project, lun, volsize, targetgroup,
-                   volblocksize='8k', sparse=False, compression=None,
-                   logbias=None):
-        """Create a LUN
-           required - pool, project, lun, volsize, targetgroup.
-           optional - volblocksize, sparse, compression, logbias
-        """
-
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + project + \
-              '/luns/' + lun
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-                  project + '/luns'
-            arg = {
-                'name': lun,
-                'volsize': volsize,
-                'targetgroup':  targetgroup,
-                'initiatorgroup': 'com.sun.ms.vss.hg.maskAll',
-                'volblocksize': volblocksize,
-                'sparse': sparse
-            }
-            if compression and compression != '':
-                arg.update({'compression': compression})
-            if logbias and logbias != '':
-                arg.update({'logbias': logbias})
-
-            ret = self.rclient.post(svc, arg)
-            if ret.status != restclient.Status.CREATED:
-                exception_msg = (_('Error Creating '
-                                   'Volume: %(lun)s '
-                                   'Size: %(size)s '
-                                   'Return code: %(ret.status)d '
-                                   'Message: %(ret.data)s.')
-                                 % {'lun': lun,
-                                    'size': volsize,
-                                    'ret.status': ret.status,
-                                    'ret.data': ret.data})
-                LOG.error(exception_msg)
-                raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def get_lun(self, pool, project, lun):
-        """return iscsi lun properties"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + "/luns/" + lun
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Getting '
-                               'Volume: %(lun)s on '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-        val = json.loads(ret.data)
-        ret = {
-            'guid': val['lun']['lunguid'],
-            'number': val['lun']['assignednumber'],
-            'initiatorgroup': val['lun']['initiatorgroup'],
-            'size': val['lun']['volsize']
-        }
-        if 'origin' in val['lun']:
-            ret.update({'origin': val['lun']['origin']})
-
-        return ret
-
-    def set_lun_initiatorgroup(self, pool, project, lun, initiatorgroup):
-        """Set the initiatorgroup property of a LUN"""
-        if initiatorgroup == '':
-            initiatorgroup = 'com.sun.ms.vss.hg.maskAll'
-
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun
-        arg = {
-            'initiatorgroup': initiatorgroup
-        }
-
-        ret = self.rclient.put(svc, arg)
-        if ret.status != restclient.Status.ACCEPTED:
-            exception_msg = (_('Error Setting '
-                               'Volume: %(lun)s to '
-                               'InitiatorGroup: %(initiatorgroup)s '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'lun': lun,
-                                'initiatorgroup': initiatorgroup,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-
-    def delete_lun(self, pool, project, lun):
-        """delete iscsi lun"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun
-
-        ret = self.rclient.delete(svc)
-        if ret.status != restclient.Status.NO_CONTENT:
-            exception_msg = (_('Error Deleting '
-                               'Volume: %(lun)s to '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-
-    def create_snapshot(self, pool, project, lun, snapshot):
-        """create snapshot"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun + '/snapshots'
-        arg = {
-            'name': snapshot
-        }
-
-        ret = self.rclient.post(svc, arg)
-        if ret.status != restclient.Status.CREATED:
-            exception_msg = (_('Error Creating '
-                               'Snapshot: %(snapshot)s on'
-                               'Volume: %(lun)s to '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'snapshot': snapshot,
-                                'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def delete_snapshot(self, pool, project, lun, snapshot):
-        """delete snapshot"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-              project + '/luns/' + lun + '/snapshots/' + snapshot
-
-        ret = self.rclient.delete(svc)
-        if ret.status != restclient.Status.NO_CONTENT:
-            exception_msg = (_('Error Deleting '
-                               'Snapshot: %(snapshot)s on '
-                               'Volume: %(lun)s to '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'snapshot': snapshot,
-                                'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def clone_snapshot(self, pool, project, lun, snapshot, clone):
-        """clone snapshot"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun + '/snapshots/' + snapshot + '/clone'
-        arg = {
-            'project': project,
-            'share': clone
-        }
-
-        ret = self.rclient.put(svc, arg)
-        if ret.status != restclient.Status.CREATED:
-            exception_msg = (_('Error Cloning '
-                               'Snapshot: %(snapshot)s on '
-                               'Volume: %(lun)s of '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'snapshot': snapshot,
-                                'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def set_lun_size(self, pool, project, lun, size):
-        """increase lun size capacity"""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun
-        arg = {
-            'volsize': size
-        }
-
-        ret = self.rclient.put(svc, arg)
-        if ret.status != restclient.Status.ACCEPTED:
-            exception_msg = (_('Error Setting size on '
-                               'Size: %(size)s on '
-                               'Volume: %(lun)s of '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'size': size,
-                                'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-    def has_clones(self, pool, project, lun, snapshot):
-        """Checks whether snapshot has clones or not."""
-        svc = '/api/storage/v1/pools/' + pool + '/projects/' + \
-            project + '/luns/' + lun + '/snapshots/' + snapshot
-
-        ret = self.rclient.get(svc)
-        if ret.status != restclient.Status.OK:
-            exception_msg = (_('Error Getting '
-                               'Snapshot: %(snapshot)s on '
-                               'Volume: %(lun)s to '
-                               'Pool: %(pool)s '
-                               'Project: %(project)s  '
-                               'Return code: %(ret.status)d '
-                               'Message: %(ret.data)s.')
-                             % {'snapshot': snapshot,
-                                'lun': lun,
-                                'pool': pool,
-                                'project': project,
-                                'ret.status': ret.status,
-                                'ret.data': ret.data})
-            LOG.error(exception_msg)
-            raise exception.VolumeBackendAPIException(data=exception_msg)
-
-        val = json.loads(ret.data)
-        return (val['snapshot']['numclones'] != 0)