示例#1
0
class ReplicationMixin(object):


    @classmethod
    def get_logger(cls):
        if (hasattr(cls, 'logger')):
            return cls.logger
        cls.logger = logging.getLogger()
        cls.logger.setLevel(logging.DEBUG)
        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)
        formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s', datefmt='%d/%b/%Y %H:%M:%S')
        ch.setFormatter(formatter)
        cls.logger.addHandler(ch)
        return cls.logger

    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception, e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)
示例#2
0
class ReplicationMixin(object):
    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception, e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)
示例#3
0
class ReplicationMixin(object):

    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception, e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)
示例#4
0
class ReplicationMixin(object):
    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception as e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)

    def disable_replica(self, rid):
        try:
            url = ('sm/replicas/%d' % rid)
            headers = {
                'content-type': 'application/json',
            }
            return self.law.api_call(url,
                                     data={
                                         'enabled': False,
                                     },
                                     calltype='put',
                                     save_error=False,
                                     headers=headers)
        except Exception as e:
            msg = ('Exception while disabling replica(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def create_replica_trail(self, rid, snap_name):
        url = ('sm/replicas/trail/replica/%d' % rid)
        return self.law.api_call(url,
                                 data={
                                     'snap_name': snap_name,
                                 },
                                 calltype='post',
                                 save_error=False)

    def rshare_id(self, sname):
        url = ('sm/replicas/rshare/%s' % sname)
        rshare = self.law.api_call(url, save_error=False)
        return rshare['id']

    def create_rshare(self, data):
        try:
            url = 'sm/replicas/rshare'
            rshare = self.law.api_call(url,
                                       data=data,
                                       calltype='post',
                                       save_error=False)
            return rshare['id']
        except RockStorAPIException as e:
            if (e.detail == 'Replicashare(%s) already exists.' %
                    data['share']):  # noqa E501
                return self.rshare_id(data['share'])
            raise e

    def create_receive_trail(self, rid, data):
        url = ('sm/replicas/rtrail/rshare/%d' % rid)
        rt = self.law.api_call(url,
                               data=data,
                               calltype='post',
                               save_error=False)
        return rt['id']

    def update_receive_trail(self, rtid, data):
        url = ('sm/replicas/rtrail/%d' % rtid)
        try:
            return self.law.api_call(url,
                                     data=data,
                                     calltype='put',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while updating receive trail(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_trail(self, url, days=7):
        try:
            data = {
                'days': days,
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype='delete',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while pruning trail for url(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_receive_trail(self, ro):
        url = ('sm/replicas/rtrail/rshare/%d' % ro.id)
        return self.prune_trail(url)

    def prune_replica_trail(self, ro):
        url = ('sm/replicas/trail/replica/%d' % ro.id)
        return self.prune_trail(url)

    def create_snapshot(self, sname, snap_name, snap_type='replication'):
        try:
            url = ('shares/%s/snapshots/%s' % (sname, snap_name))
            return self.law.api_call(url,
                                     data={
                                         'snap_type': snap_type,
                                     },
                                     calltype='post',
                                     save_error=False)
        except RockStorAPIException as e:
            if (e.detail == ('Snapshot(%s) already exists for the Share(%s).' %
                             (snap_name, sname))):
                return logger.debug(e.detail)
            raise e

    def delete_snapshot(self, sname, snap_name):
        try:
            url = ('shares/%s/snapshots/%s' % (sname, snap_name))
            self.law.api_call(url, calltype='delete', save_error=False)
            return True
        except RockStorAPIException as e:
            if (e.detail == 'Snapshot(%s) does not exist.' % snap_name):
                logger.debug(e.detail)
                return False
            raise e

    def create_share(self, sname, pool):
        try:
            url = 'shares'
            data = {
                'pool': pool,
                'replica': True,
                'sname': sname,
            }
            headers = {
                'content-type': 'application/json',
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype='post',
                                     headers=headers,
                                     save_error=False)
        except RockStorAPIException as e:
            if (e.detail == 'Share(%s) already exists. Choose a different name'
                    % sname):  # noqa E501
                return logger.debug(e.detail)
            raise e

    def refresh_snapshot_state(self):
        try:
            return self.law.api_call('commands/refresh-snapshot-state',
                                     data=None,
                                     calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Snapshot state: %s' %
                         e.__str__())

    def refresh_share_state(self):
        try:
            return self.law.api_call('commands/refresh-share-state',
                                     data=None,
                                     calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refresh Shar state: %s' %
                         e.__str__())

    def humanize_bytes(self, num, units=(
        'Bytes',
        'KB',
        'MB',
        'GB',
    )):
        if (num < 1024 or len(units) == 1):
            return '%.2f %s' % (num, units[0])
        return self.humanize_bytes(num / 1024, units[1:])

    def size_report(self, num, t0):
        t1 = time.time()
        dsize = self.humanize_bytes(float(num))
        drate = self.humanize_bytes(float(num / (t1 - t0)))
        return dsize, drate
示例#5
0
class ReplicationMixin(object):
    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        # TODO: update url to include senders shareId as sname is now invalid
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception as e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)

    def disable_replica(self, rid):
        try:
            url = ('sm/replicas/%d' % rid)
            headers = {
                'content-type': 'application/json',
            }
            return self.law.api_call(url,
                                     data={
                                         'enabled': False,
                                     },
                                     calltype='put',
                                     save_error=False,
                                     headers=headers)
        except Exception as e:
            msg = ('Exception while disabling replica(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def create_replica_trail(self, rid, snap_name):
        url = ('sm/replicas/trail/replica/%d' % rid)
        return self.law.api_call(url,
                                 data={
                                     'snap_name': snap_name,
                                 },
                                 calltype='post',
                                 save_error=False)

    def rshare_id(self, sname):
        url = ('sm/replicas/rshare/%s' % sname)
        rshare = self.law.api_call(url, save_error=False)
        return rshare['id']

    def create_rshare(self, data):
        try:
            url = 'sm/replicas/rshare'
            rshare = self.law.api_call(url,
                                       data=data,
                                       calltype='post',
                                       save_error=False)
            return rshare['id']
        except RockStorAPIException as e:
            # Note replica_share.py post() generates this exception message.
            if (e.detail == 'Replicashare(%s) already exists.' %
                    data['share']):  # noqa E501
                return self.rshare_id(data['share'])
            raise e

    def create_receive_trail(self, rid, data):
        url = ('sm/replicas/rtrail/rshare/%d' % rid)
        rt = self.law.api_call(url,
                               data=data,
                               calltype='post',
                               save_error=False)
        return rt['id']

    def update_receive_trail(self, rtid, data):
        url = ('sm/replicas/rtrail/%d' % rtid)
        try:
            return self.law.api_call(url,
                                     data=data,
                                     calltype='put',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while updating receive trail(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_trail(self, url, days=7):
        try:
            data = {
                'days': days,
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype='delete',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while pruning trail for url(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_receive_trail(self, ro):
        url = ('sm/replicas/rtrail/rshare/%d' % ro.id)
        return self.prune_trail(url)

    def prune_replica_trail(self, ro):
        url = ('sm/replicas/trail/replica/%d' % ro.id)
        return self.prune_trail(url)

    def create_snapshot(self, sname, snap_name, snap_type='replication'):
        try:
            share = Share.objects.get(name=sname)
            url = ('shares/%s/snapshots/%s' % (share.id, snap_name))
            return self.law.api_call(url,
                                     data={
                                         'snap_type': snap_type,
                                     },
                                     calltype='post',
                                     save_error=False)
        except RockStorAPIException as e:
            # Note snapshot.py _create() generates this exception message.
            if (e.detail == ('Snapshot ({}) already exists for the share '
                             '({}).').format(snap_name, sname)):
                return logger.debug(e.detail)
            raise e

    def update_repclone(self, sname, snap_name):
        """
        Call the dedicated create_repclone via it's url to supplant our
        share with the given snapshot. Intended for use in receive.py to turn
        the oldest snapshot into an existing share via unmount, mv, mount
        cycle.
        :param sname: Existing share name
        :param snap_name: Name of snapshot to supplant given share with.
        :return: False if there is a failure.
        """
        try:
            share = Share.objects.get(name=sname)
            url = 'shares/{}/snapshots/{}/repclone'.format(share.id, snap_name)
            return self.law.api_call(url, calltype='post', save_error=False)
        except RockStorAPIException as e:
            # TODO: need to look further at the following as command repclone
            # TODO: (snapshot.py post) catches Snapshot.DoesNotExist.
            # TODO: and doesn't appear to call _delete_snapshot()
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if (e.detail == 'Snapshot name ({}) does not '
                    'exist.'.format(snap_name)):
                logger.debug(e.detail)
                return False
            raise e

    def delete_snapshot(self, sname, snap_name):
        try:
            share = Share.objects.get(name=sname)
            url = ('shares/%s/snapshots/%s' % (share.id, snap_name))
            self.law.api_call(url, calltype='delete', save_error=False)
            return True
        except RockStorAPIException as e:
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if (e.detail == 'Snapshot name ({}) does not '
                    'exist.'.format(snap_name)):
                logger.debug(e.detail)
                return False
            raise e

    def create_share(self, sname, pool):
        try:
            url = 'shares'
            data = {
                'pool': pool,
                'replica': True,
                'sname': sname,
            }
            headers = {
                'content-type': 'application/json',
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype='post',
                                     headers=headers,
                                     save_error=False)
        except RockStorAPIException as e:
            # Note share.py post() generates this exception message.
            if (e.detail == 'Share ({}) already exists. Choose a different '
                    'name.'.format(sname)):  # noqa E501
                return logger.debug(e.detail)
            raise e

    def refresh_snapshot_state(self):
        try:
            return self.law.api_call('commands/refresh-snapshot-state',
                                     data=None,
                                     calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Snapshot state: %s' %
                         e.__str__())

    def refresh_share_state(self):
        try:
            return self.law.api_call('commands/refresh-share-state',
                                     data=None,
                                     calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Share state: %s' %
                         e.__str__())

    def humanize_bytes(self, num, units=(
        'Bytes',
        'KB',
        'MB',
        'GB',
    )):
        """
        Recursive routine to establish and then return the most appropriate
        num expression given the contents of units. Ie 1023 Bytes or 4096 KB
        :param num: Assumed to be in Byte units.
        :param units: list of units to recurse through
        :return: "1023 Bytes" or "4.28 KB" etc given num=1023 or num=4384 )
        """
        if (num < 1024 or len(units) == 1):
            return '%.2f %s' % (num, units[0])
        return self.humanize_bytes(num / 1024, units[1:])

    def size_report(self, num, t0):
        t1 = time.time()
        dsize = self.humanize_bytes(float(num))
        drate = self.humanize_bytes(float(num / (t1 - t0)))
        return dsize, drate
示例#6
0
class ReplicationMixin(object):
    def validate_src_share(self, sender_uuid, sname):
        url = "https://"
        if self.raw is None:
            a = Appliance.objects.get(uuid=sender_uuid)
            url = "%s%s:%s" % (url, a.ip, a.mgmt_port)
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        # TODO: update url to include senders shareId as sname is now invalid
        return self.raw.api_call(url="shares/%s" % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = "sm/replicas/trail/%d" % rtid
            return self.law.api_call(url, data=data, calltype="put")
        except Exception as e:
            msg = "Exception while updating replica(%s) status to %s: %s" % (
                url,
                data["status"],
                e.__str__(),
            )
            raise Exception(msg)

    def disable_replica(self, rid):
        try:
            url = "sm/replicas/%d" % rid
            headers = {
                "content-type": "application/json",
            }
            return self.law.api_call(
                url,
                data={
                    "enabled": False,
                },
                calltype="put",
                save_error=False,
                headers=headers,
            )
        except Exception as e:
            msg = "Exception while disabling replica(%s): %s" % (url,
                                                                 e.__str__())
            raise Exception(msg)

    def create_replica_trail(self, rid, snap_name):
        url = "sm/replicas/trail/replica/%d" % rid
        return self.law.api_call(url,
                                 data={
                                     "snap_name": snap_name,
                                 },
                                 calltype="post",
                                 save_error=False)

    def rshare_id(self, sname):
        url = "sm/replicas/rshare/%s" % sname
        rshare = self.law.api_call(url, save_error=False)
        return rshare["id"]

    def create_rshare(self, data):
        try:
            url = "sm/replicas/rshare"
            rshare = self.law.api_call(url,
                                       data=data,
                                       calltype="post",
                                       save_error=False)
            return rshare["id"]
        except RockStorAPIException as e:
            # Note replica_share.py post() generates this exception message.
            if (e.detail == "Replicashare(%s) already exists." %
                    data["share"]):  # noqa E501
                return self.rshare_id(data["share"])
            raise e

    def create_receive_trail(self, rid, data):
        url = "sm/replicas/rtrail/rshare/%d" % rid
        rt = self.law.api_call(url,
                               data=data,
                               calltype="post",
                               save_error=False)
        return rt["id"]

    def update_receive_trail(self, rtid, data):
        url = "sm/replicas/rtrail/%d" % rtid
        try:
            return self.law.api_call(url,
                                     data=data,
                                     calltype="put",
                                     save_error=False)
        except Exception as e:
            msg = "Exception while updating receive trail(%s): %s" % (
                url, e.__str__())
            raise Exception(msg)

    def prune_trail(self, url, days=7):
        try:
            data = {
                "days": days,
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype="delete",
                                     save_error=False)
        except Exception as e:
            msg = "Exception while pruning trail for url(%s): %s" % (
                url, e.__str__())
            raise Exception(msg)

    def prune_receive_trail(self, ro):
        url = "sm/replicas/rtrail/rshare/%d" % ro.id
        return self.prune_trail(url)

    def prune_replica_trail(self, ro):
        url = "sm/replicas/trail/replica/%d" % ro.id
        return self.prune_trail(url)

    def create_snapshot(self, sname, snap_name, snap_type="replication"):
        try:
            share = Share.objects.get(name=sname)
            url = "shares/%s/snapshots/%s" % (share.id, snap_name)
            return self.law.api_call(url,
                                     data={
                                         "snap_type": snap_type,
                                     },
                                     calltype="post",
                                     save_error=False)
        except RockStorAPIException as e:
            # Note snapshot.py _create() generates this exception message.
            if e.detail == (
                    "Snapshot ({}) already exists for the share ({}).").format(
                        snap_name, sname):
                return logger.debug(e.detail)
            raise e

    def update_repclone(self, sname, snap_name):
        """
        Call the dedicated create_repclone via it's url to supplant our
        share with the given snapshot. Intended for use in receive.py to turn
        the oldest snapshot into an existing share via unmount, mv, mount
        cycle.
        :param sname: Existing share name
        :param snap_name: Name of snapshot to supplant given share with.
        :return: False if there is a failure.
        """
        try:
            share = Share.objects.get(name=sname)
            url = "shares/{}/snapshots/{}/repclone".format(share.id, snap_name)
            return self.law.api_call(url, calltype="post", save_error=False)
        except RockStorAPIException as e:
            # TODO: need to look further at the following as command repclone
            # TODO: (snapshot.py post) catches Snapshot.DoesNotExist.
            # TODO: and doesn't appear to call _delete_snapshot()
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if e.detail == "Snapshot name ({}) does not exist.".format(
                    snap_name):
                logger.debug(e.detail)
                return False
            raise e

    def delete_snapshot(self, sname, snap_name):
        try:
            share = Share.objects.get(name=sname)
            url = "shares/%s/snapshots/%s" % (share.id, snap_name)
            self.law.api_call(url, calltype="delete", save_error=False)
            return True
        except RockStorAPIException as e:
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if e.detail == "Snapshot name ({}) does not exist.".format(
                    snap_name):
                logger.debug(e.detail)
                return False
            raise e

    def create_share(self, sname, pool):
        try:
            url = "shares"
            data = {
                "pool": pool,
                "replica": True,
                "sname": sname,
            }
            headers = {
                "content-type": "application/json",
            }
            return self.law.api_call(url,
                                     data=data,
                                     calltype="post",
                                     headers=headers,
                                     save_error=False)
        except RockStorAPIException as e:
            # Note share.py post() generates this exception message.
            if (e.detail == "Share ({}) already exists. Choose a different "
                    "name.".format(sname)):  # noqa E501
                return logger.debug(e.detail)
            raise e

    def refresh_snapshot_state(self):
        try:
            return self.law.api_call(
                "commands/refresh-snapshot-state",
                data=None,
                calltype="post",
                save_error=False,
            )
        except Exception as e:
            logger.error("Exception while refreshing Snapshot state: %s" %
                         e.__str__())

    def refresh_share_state(self):
        try:
            return self.law.api_call(
                "commands/refresh-share-state",
                data=None,
                calltype="post",
                save_error=False,
            )
        except Exception as e:
            logger.error("Exception while refreshing Share state: %s" %
                         e.__str__())

    def humanize_bytes(self, num, units=(
        "Bytes",
        "KB",
        "MB",
        "GB",
    )):
        """
        Recursive routine to establish and then return the most appropriate
        num expression given the contents of units. Ie 1023 Bytes or 4096 KB
        :param num: Assumed to be in Byte units.
        :param units: list of units to recurse through
        :return: "1023 Bytes" or "4.28 KB" etc given num=1023 or num=4384 )
        """
        if num < 1024 or len(units) == 1:
            return "%.2f %s" % (num, units[0])
        return self.humanize_bytes(num / 1024, units[1:])

    def size_report(self, num, t0):
        t1 = time.time()
        dsize = self.humanize_bytes(float(num))
        drate = self.humanize_bytes(float(num / (t1 - t0)))
        return dsize, drate
示例#7
0
class ReplicationMixin(object):

    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception as e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)

    def disable_replica(self, rid):
        try:
            url = ('sm/replicas/%d' % rid)
            headers = {'content-type': 'application/json', }
            return self.law.api_call(url, data={'enabled': False, },
                                     calltype='put', save_error=False,
                                     headers=headers)
        except Exception as e:
            msg = ('Exception while disabling replica(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def create_replica_trail(self, rid, snap_name):
        url = ('sm/replicas/trail/replica/%d' % rid)
        return self.law.api_call(url, data={'snap_name': snap_name, },
                                 calltype='post', save_error=False)

    def rshare_id(self, sname):
        url = ('sm/replicas/rshare/%s' % sname)
        rshare = self.law.api_call(url, save_error=False)
        return rshare['id']

    def create_rshare(self, data):
        try:
            url = 'sm/replicas/rshare'
            rshare = self.law.api_call(url, data=data, calltype='post',
                                       save_error=False)
            return rshare['id']
        except RockStorAPIException as e:
            if (e.detail == 'Replicashare(%s) already exists.' % data['share']):  # noqa E501
                return self.rshare_id(data['share'])
            raise e

    def create_receive_trail(self, rid, data):
        url = ('sm/replicas/rtrail/rshare/%d' % rid)
        rt = self.law.api_call(url, data=data, calltype='post',
                               save_error=False)
        return rt['id']

    def update_receive_trail(self, rtid, data):
        url = ('sm/replicas/rtrail/%d' % rtid)
        try:
            return self.law.api_call(url, data=data, calltype='put',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while updating receive trail(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_trail(self, url, days=7):
        try:
            data = {'days': days, }
            return self.law.api_call(url, data=data, calltype='delete',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while pruning trail for url(%s): %s'
                   % (url, e.__str__()))
            raise Exception(msg)

    def prune_receive_trail(self, ro):
        url = ('sm/replicas/rtrail/rshare/%d' % ro.id)
        return self.prune_trail(url)

    def prune_replica_trail(self, ro):
        url = ('sm/replicas/trail/replica/%d' % ro.id)
        return self.prune_trail(url)

    def create_snapshot(self, sname, snap_name, snap_type='replication'):
        try:
            url = ('shares/%s/snapshots/%s' % (sname, snap_name))
            return self.law.api_call(url, data={'snap_type': snap_type, },
                                     calltype='post', save_error=False)
        except RockStorAPIException as e:
            if (e.detail == ('Snapshot(%s) already exists for the Share(%s).' %
                             (snap_name, sname))):
                return logger.debug(e.detail)
            raise e

    def delete_snapshot(self, sname, snap_name):
        try:
            url = ('shares/%s/snapshots/%s' % (sname, snap_name))
            self.law.api_call(url, calltype='delete', save_error=False)
            return True
        except RockStorAPIException as e:
            if (e.detail == 'Snapshot(%s) does not exist.' % snap_name):
                logger.debug(e.detail)
                return False
            raise e

    def create_share(self, sname, pool):
        try:
            url = 'shares'
            data = {'pool': pool,
                    'replica': True,
                    'sname': sname, }
            headers = {'content-type': 'application/json', }
            return self.law.api_call(url, data=data, calltype='post',
                                     headers=headers, save_error=False)
        except RockStorAPIException as e:
            if (e.detail == 'Share(%s) already exists. Choose a different name' % sname):  # noqa E501
                return logger.debug(e.detail)
            raise e

    def refresh_snapshot_state(self):
        try:
            return self.law.api_call('commands/refresh-snapshot-state',
                                     data=None, calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Snapshot state: %s'
                         % e.__str__())

    def refresh_share_state(self):
        try:
            return self.law.api_call('commands/refresh-share-state', data=None,
                                     calltype='post', save_error=False)
        except Exception as e:
            logger.error('Exception while refresh Shar state: %s'
                         % e.__str__())

    def humanize_bytes(self, num, units=('Bytes', 'KB', 'MB', 'GB',)):
        if (num < 1024 or len(units) == 1):
            return '%.2f %s' % (num, units[0])
        return self.humanize_bytes(num/1024, units[1:])

    def size_report(self, num, t0):
        t1 = time.time()
        dsize = self.humanize_bytes(float(num))
        drate = self.humanize_bytes(float(num/(t1 - t0)))
        return dsize, drate
示例#8
0
class ReplicationMixin(object):

    def validate_src_share(self, sender_uuid, sname):
        url = 'https://'
        if (self.raw is None):
            a = Appliance.objects.get(uuid=sender_uuid)
            url = ('%s%s:%s' % (url, a.ip, a.mgmt_port))
            self.raw = APIWrapper(client_id=a.client_id,
                                  client_secret=a.client_secret,
                                  url=url)
        # TODO: update url to include senders shareId as sname is now invalid
        return self.raw.api_call(url='shares/%s' % sname)

    def update_replica_status(self, rtid, data):
        try:
            url = ('sm/replicas/trail/%d' % rtid)
            return self.law.api_call(url, data=data, calltype='put')
        except Exception as e:
            msg = ('Exception while updating replica(%s) status to %s: %s' %
                   (url, data['status'], e.__str__()))
            raise Exception(msg)

    def disable_replica(self, rid):
        try:
            url = ('sm/replicas/%d' % rid)
            headers = {'content-type': 'application/json', }
            return self.law.api_call(url, data={'enabled': False, },
                                     calltype='put', save_error=False,
                                     headers=headers)
        except Exception as e:
            msg = ('Exception while disabling replica(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def create_replica_trail(self, rid, snap_name):
        url = ('sm/replicas/trail/replica/%d' % rid)
        return self.law.api_call(url, data={'snap_name': snap_name, },
                                 calltype='post', save_error=False)

    def rshare_id(self, sname):
        url = ('sm/replicas/rshare/%s' % sname)
        rshare = self.law.api_call(url, save_error=False)
        return rshare['id']

    def create_rshare(self, data):
        try:
            url = 'sm/replicas/rshare'
            rshare = self.law.api_call(url, data=data, calltype='post',
                                       save_error=False)
            return rshare['id']
        except RockStorAPIException as e:
            # Note replica_share.py post() generates this exception message.
            if (e.detail == 'Replicashare(%s) already exists.' % data['share']):  # noqa E501
                return self.rshare_id(data['share'])
            raise e

    def create_receive_trail(self, rid, data):
        url = ('sm/replicas/rtrail/rshare/%d' % rid)
        rt = self.law.api_call(url, data=data, calltype='post',
                               save_error=False)
        return rt['id']

    def update_receive_trail(self, rtid, data):
        url = ('sm/replicas/rtrail/%d' % rtid)
        try:
            return self.law.api_call(url, data=data, calltype='put',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while updating receive trail(%s): %s' %
                   (url, e.__str__()))
            raise Exception(msg)

    def prune_trail(self, url, days=7):
        try:
            data = {'days': days, }
            return self.law.api_call(url, data=data, calltype='delete',
                                     save_error=False)
        except Exception as e:
            msg = ('Exception while pruning trail for url(%s): %s'
                   % (url, e.__str__()))
            raise Exception(msg)

    def prune_receive_trail(self, ro):
        url = ('sm/replicas/rtrail/rshare/%d' % ro.id)
        return self.prune_trail(url)

    def prune_replica_trail(self, ro):
        url = ('sm/replicas/trail/replica/%d' % ro.id)
        return self.prune_trail(url)

    def create_snapshot(self, sname, snap_name, snap_type='replication'):
        try:
            share = Share.objects.get(name=sname)
            url = ('shares/%s/snapshots/%s' % (share.id, snap_name))
            return self.law.api_call(url, data={'snap_type': snap_type, },
                                     calltype='post', save_error=False)
        except RockStorAPIException as e:
            # Note snapshot.py _create() generates this exception message.
            if (e.detail == ('Snapshot ({}) already exists for the share '
                             '({}).').format(snap_name, sname)):
                return logger.debug(e.detail)
            raise e

    def update_repclone(self, sname, snap_name):
        """
        Call the dedicated create_repclone via it's url to supplant our
        share with the given snapshot. Intended for use in receive.py to turn
        the oldest snapshot into an existing share via unmount, mv, mount
        cycle.
        :param sname: Existing share name
        :param snap_name: Name of snapshot to supplant given share with.
        :return: False if there is a failure.
        """
        try:
            share = Share.objects.get(name=sname)
            url = 'shares/{}/snapshots/{}/repclone'.format(share.id, snap_name)
            return self.law.api_call(url, calltype='post', save_error=False)
        except RockStorAPIException as e:
            # TODO: need to look further at the following as command repclone
            # TODO: (snapshot.py post) catches Snapshot.DoesNotExist.
            # TODO: and doesn't appear to call _delete_snapshot()
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if (e.detail == 'Snapshot name ({}) does not '
                            'exist.'.format(snap_name)):
                logger.debug(e.detail)
                return False
            raise e

    def delete_snapshot(self, sname, snap_name):
        try:
            share = Share.objects.get(name=sname)
            url = ('shares/%s/snapshots/%s' % (share.id, snap_name))
            self.law.api_call(url, calltype='delete', save_error=False)
            return True
        except RockStorAPIException as e:
            # Note snapshot.py _delete_snapshot() generates this exception msg.
            if (e.detail == 'Snapshot name ({}) does not '
                            'exist.'.format(snap_name)):
                logger.debug(e.detail)
                return False
            raise e

    def create_share(self, sname, pool):
        try:
            url = 'shares'
            data = {'pool': pool,
                    'replica': True,
                    'sname': sname, }
            headers = {'content-type': 'application/json', }
            return self.law.api_call(url, data=data, calltype='post',
                                     headers=headers, save_error=False)
        except RockStorAPIException as e:
            # Note share.py post() generates this exception message.
            if (e.detail == 'Share ({}) already exists. Choose a different '
                            'name.'.format(sname)):  # noqa E501
                return logger.debug(e.detail)
            raise e

    def refresh_snapshot_state(self):
        try:
            return self.law.api_call('commands/refresh-snapshot-state',
                                     data=None, calltype='post',
                                     save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Snapshot state: %s'
                         % e.__str__())

    def refresh_share_state(self):
        try:
            return self.law.api_call('commands/refresh-share-state', data=None,
                                     calltype='post', save_error=False)
        except Exception as e:
            logger.error('Exception while refreshing Share state: %s'
                         % e.__str__())

    def humanize_bytes(self, num, units=('Bytes', 'KB', 'MB', 'GB',)):
        """
        Recursive routine to establish and then return the most appropriate
        num expression given the contents of units. Ie 1023 Bytes or 4096 KB
        :param num: Assumed to be in Byte units.
        :param units: list of units to recurse through
        :return: "1023 Bytes" or "4.28 KB" etc given num=1023 or num=4384 )
        """
        if (num < 1024 or len(units) == 1):
            return '%.2f %s' % (num, units[0])
        return self.humanize_bytes(num/1024, units[1:])

    def size_report(self, num, t0):
        t1 = time.time()
        dsize = self.humanize_bytes(float(num))
        drate = self.humanize_bytes(float(num/(t1 - t0)))
        return dsize, drate