def post(self, request, sname): with self._handle_exception(request): share = Share.objects.get(name=sname) options = { 'owner': 'root', 'group': 'root', 'perms': '755', 'orecursive': True, 'precursive': True, } options['owner'] = request.data.get('owner', options['owner']) options['group'] = request.data.get('group', options['group']) options['perms'] = request.data.get('perms', options['perms']) options['orecursive'] = request.data.get('orecursive', options['orecursive']) options['precursive'] = request.data.get('precursive', options['precursive']) share.owner = options['owner'] share.group = options['group'] share.perms = options['perms'] share.save() mnt_pt = ('%s%s' % (settings.MNT_PT, share.name)) force_mount = False if (not is_share_mounted(share.name)): pool_device = Disk.objects.filter(pool=share.pool)[0].name mount_share(share, pool_device, mnt_pt) force_mount = True chown(mnt_pt, options['owner'], options['group'], options['orecursive']) chmod(mnt_pt, options['perms'], options['precursive']) if (force_mount is True): umount_root(mnt_pt) return Response(ShareSerializer(share).data)
def create_clone(share, new_name, request, logger, snapshot=None): # if snapshot is None, create clone of the share. # If it's not, then clone it. if (re.match(settings.SHARE_REGEX + '$', new_name) is None): e_msg = ('Clone name is invalid. It must start with a letter and can' ' contain letters, digits, _, . and - characters') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=new_name).exists()): e_msg = ('Another Share with name: %s already exists.' % new_name) handle_exception(Exception(e_msg), request) if (Snapshot.objects.filter(share=share, name=new_name).exists()): e_msg = ('Snapshot with name: %s already exists for the ' 'share: %s. Choose a different name' % (new_name, share.name)) handle_exception(Exception(e_msg), request) try: share_name = share.subvol_name snap = None if (snapshot is not None): snap = snapshot.real_name add_clone(share.pool, share_name, new_name, snapshot=snap) snap_id = share_id(share.pool, new_name) qgroup_id = ('0/%s' % snap_id) update_quota(share.pool, qgroup_id, share.size * 1024) new_share = Share(pool=share.pool, qgroup=qgroup_id, name=new_name, size=share.size, subvol_name=new_name) new_share.save() return Response(ShareSerializer(new_share).data) except Exception as e: handle_exception(e, request)
def create_clone(share, new_name, request, logger): if (Share.objects.filter(name=new_name).exists()): e_msg = ('Share with name: %s already exists.' % new_name) handle_exception(Exception(e_msg), request) pool_device = Disk.objects.filter(pool=share.pool)[0].name snap_name = ('%s-clone-%s-snapshot' % (share.name, new_name)) if (Snapshot.objects.filter(share=share, name=snap_name).exists()): e_msg = ('Snapshot with name: %s already exists for the ' 'share: %s' % (snap_name, share.name)) handle_exception(Exception(e_msg), request) try: add_snap(share.pool.name, pool_device, share.subvol_name, snap_name, share_prepend=False) snap_id = share_id(share.pool.name, pool_device, snap_name) qgroup_id = ('0/%s' % snap_id) update_quota(share.pool.name, pool_device, qgroup_id, share.size * 1024) new_share = Share(pool=share.pool, qgroup=qgroup_id, name=new_name, size=share.size, subvol_name=snap_name) new_share.save() return Response(ShareSerializer(new_share).data) except Exception, e: e_msg = ('Failed to create clone due to a system error.') logger.error(e_msg) logger.exception(e) handle_exception(Exception(e_msg), request)
def post(self, request, sid): with self._handle_exception(request): share = Share.objects.get(id=sid) options = { "owner": "root", "group": "root", "perms": "755", "orecursive": True, "precursive": True, } options["owner"] = request.data.get("owner", options["owner"]) options["group"] = request.data.get("group", options["group"]) options["perms"] = request.data.get("perms", options["perms"]) options["orecursive"] = request.data.get( "orecursive", options["orecursive"] ) options["precursive"] = request.data.get( "precursive", options["precursive"] ) share.owner = options["owner"] share.group = options["group"] share.perms = options["perms"] share.save() mnt_pt = "%s%s" % (settings.MNT_PT, share.name) force_mount = False if not share.is_mounted: mount_share(share, mnt_pt) force_mount = True chown(mnt_pt, options["owner"], options["group"], options["orecursive"]) chmod(mnt_pt, options["perms"], options["precursive"]) if force_mount is True: umount_root(mnt_pt) return Response(ShareSerializer(share).data)
def get(self, *args, **kwargs): try: data = Share.objects.get(id=self.kwargs['sid']) serialized_data = ShareSerializer(data) return Response(serialized_data.data) except Share.DoesNotExist: raise NotFound(detail=None)
def put(self, request, sname): try: if (not Share.objects.filter(name=sname).exists()): e_msg = ('Share with name: %s does not exist' % sname) handle_exception(Exception(e_msg), request) share = Share.objects.get(name=sname) new_size = int(request.DATA['size']) self._validate_share_size(request, new_size) disk = Disk.objects.filter(pool=share.pool)[0] qgroup_id = self._update_quota(share.pool.name, disk.name, sname, new_size) cur_usage = share_usage(share.pool.name, disk.name, qgroup_id) if (new_size < cur_usage): e_msg = ('Unable to resize because requested new size(%dKB) ' 'is less than current usage(%dKB) of the share.' % (new_size, cur_usage)) handle_exception(Exception(e_msg), request) share.size = new_size share.save() return Response(ShareSerializer(share).data) except RockStorAPIException: raise except Exception, e: handle_exception(e, request)
def put(self, request, sname): with self._handle_exception(request): share = self._validate_share(request, sname) if ('size' in request.data): new_size = self._validate_share_size(request, share.pool) disk = Disk.objects.filter(pool=share.pool)[0] qid = qgroup_id(share.pool, share.subvol_name) cur_rusage, cur_eusage = share_usage(share.pool, qid) if (new_size < cur_rusage): e_msg = ( 'Unable to resize because requested new size(%dKB) ' 'is less than current usage(%dKB) of the share.' % (new_size, cur_rusage)) handle_exception(Exception(e_msg), request) update_quota(share.pool, share.pqgroup, new_size * 1024) share.size = new_size if ('compression' in request.data): new_compression = self._validate_compression(request) if (share.compression_algo != new_compression): share.compression_algo = new_compression mnt_pt = '%s%s' % (settings.MNT_PT, sname) if (new_compression == 'no'): new_compression = '' set_property(mnt_pt, 'compression', new_compression) share.save() return Response(ShareSerializer(share).data)
def post(self, request): with self._handle_exception(request): pool_name = request.data.get('pool', None) try: pool = Pool.objects.get(name=pool_name) except: e_msg = ('Pool(%s) does not exist.' % pool_name) handle_exception(Exception(e_msg), request) compression = self._validate_compression(request) size = self._validate_share_size(request, pool) sname = request.data.get('sname', None) if ((sname is None or re.match('%s$' % settings.SHARE_REGEX, sname) is None)): e_msg = ('Share name must start with a alphanumeric(a-z0-9) ' 'character and can be followed by any of the ' 'following characters: letter(a-z), digits(0-9), ' 'hyphen(-), underscore(_) or a period(.).') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=sname).exists()): e_msg = ('Share(%s) already exists. Choose a different name' % sname) handle_exception(Exception(e_msg), request) if (Pool.objects.filter(name=sname).exists()): e_msg = ( 'A Pool with this name(%s) exists. Share and Pool names ' 'must be distinct. Choose a different name' % sname) handle_exception(Exception(e_msg), request) disk = Disk.objects.filter(pool=pool)[0] replica = False if ('replica' in request.data): replica = request.data['replica'] if (type(replica) != bool): e_msg = ('replica must be a boolean, not %s' % type(replica)) handle_exception(Exception(e_msg), request) add_share(pool, disk.name, sname) qid = qgroup_id(pool, disk.name, sname) update_quota(pool, disk.name, qid, size * 1024) s = Share(pool=pool, qgroup=qid, name=sname, size=size, subvol_name=sname, replica=replica, compression_algo=compression) s.save() mnt_pt = '%s%s' % (settings.MNT_PT, sname) if (not is_share_mounted(sname)): disk = Disk.objects.filter(pool=pool)[0].name mount_share(s, disk, mnt_pt) if (compression != 'no'): set_property(mnt_pt, 'compression', compression) return Response(ShareSerializer(s).data)
def post(self, request): try: sname = request.DATA['sname'] if (re.match('%s$' % settings.SHARE_REGEX, sname) is None): e_msg = ('Share name must start with a letter(a-z) and can' ' be followed by any of the following characters: ' 'letter(a-z), digits(0-9), hyphen(-), underscore' '(_) or a period(.).') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=sname).exists()): e_msg = ('Share with name: %s already exists.' % sname) handle_exception(Exception(e_msg), request) pool_name = request.DATA['pool'] size = int(request.DATA['size']) #in KB self._validate_share_size(request, size) pool = None try: pool = Pool.objects.get(name=pool_name) except: e_msg = ('Pool with name: %s does not exist.' % pool_name) handle_exception(Exception(e_msg), request) disk = None try: disk = Disk.objects.filter(pool=pool)[0] except: e_msg = ('Pool with name: %s does not have any disks in it.' % pool_name) handle_exception(Exception(e_msg), request) replica = False if ('replica' in request.DATA): replica = request.DATA['replica'] if (type(replica) != bool): e_msg = ('replica must be a boolean, not %s' % type(replica)) handle_exception(Exception(e_msg), request) add_share(pool_name, disk.name, sname) qgroup_id = self._update_quota(pool_name, disk.name, sname, size) s = Share(pool=pool, qgroup=qgroup_id, name=sname, size=size, subvol_name=sname, replica=replica) s.save() return Response(ShareSerializer(s).data) except RockStorAPIException: raise except Exception, e: handle_exception(e, request)
def put(self, request, sid): with self._handle_exception(request): share = self._validate_share(request, sid) if ('size' in request.data): new_size = self._validate_share_size(request, share.pool) qid = qgroup_id(share.pool, share.subvol_name) cur_rusage, cur_eusage = volume_usage(share.pool, qid) if (new_size < cur_rusage): e_msg = ('Unable to resize because requested new ' 'size {} KB is less than current usage {} KB ' 'of the share.').format(new_size, cur_rusage) handle_exception(Exception(e_msg), request) # quota maintenance if share.pool.quotas_enabled: # Only try create / update quotas if they are enabled, # pqgroup of PQGROUP_DEFAULT (-1/-1) indicates no pqgroup, # ie quotas were disabled when update was requested. if share.pqgroup == PQGROUP_DEFAULT or \ not share.pqgroup_exist: # if quotas were disabled or pqgroup non-existent. share.pqgroup = qgroup_create(share.pool) share.save() if share.pqgroup is not PQGROUP_DEFAULT: # Only update quota and assign if now non default as # default can also indicate Read-only fs at this point. update_quota(share.pool, share.pqgroup, new_size * 1024) share_pqgroup_assign(share.pqgroup, share) else: # Our pool's quotas are disabled so reset pqgroup to -1/-1. if share.pqgroup != PQGROUP_DEFAULT: # Only reset if necessary share.pqgroup = PQGROUP_DEFAULT share.save() share.size = new_size if ('compression' in request.data): new_compression = self._validate_compression(request) if (share.compression_algo != new_compression): share.compression_algo = new_compression mnt_pt = '%s%s' % (settings.MNT_PT, share.name) if (new_compression == 'no'): new_compression = '' set_property(mnt_pt, 'compression', new_compression) share.save() return Response(ShareSerializer(share).data)
def create_clone(share, new_name, request, logger, snapshot=None): # if snapshot is None, create clone of the share. # If it's not, then clone it. if re.match(settings.SHARE_REGEX + "$", new_name) is None: e_msg = ("Clone name is invalid. It must start with a letter and can " "contain letters, digits, _, . and - characters.") handle_exception(Exception(e_msg), request) if Share.objects.filter(name=new_name).exists(): e_msg = "Another share with name ({}) already exists.".format(new_name) handle_exception(Exception(e_msg), request) if Snapshot.objects.filter(share=share, name=new_name).exists(): e_msg = ("Snapshot with name ({}) already exists for the " "share ({}). Choose a different name.").format( new_name, share.name) handle_exception(Exception(e_msg), request) try: share_name = share.subvol_name snap = None if snapshot is not None: snap = snapshot.real_name add_clone(share.pool, share_name, new_name, snapshot=snap) snap_id = share_id(share.pool, new_name) qgroup_id = "0/{}".format(snap_id) pqid = qgroup_create(share.pool) new_share = Share( pool=share.pool, qgroup=qgroup_id, pqgroup=pqid, name=new_name, size=share.size, subvol_name=new_name, ) new_share.save() if pqid != PQGROUP_DEFAULT: update_quota(new_share.pool, pqid, new_share.size * 1024) share_pqgroup_assign(pqid, new_share) # Mount our new clone share. # We independently mount all shares, data pool or system pool, in /mnt2/name mnt_pt = "{}{}".format(settings.MNT_PT, new_name) mount_share(new_share, mnt_pt) return Response(ShareSerializer(new_share).data) except Exception as e: handle_exception(e, request)
def post(self, request, sname): try: share = Share.objects.get(name=sname) options = { 'owner': 'root', 'group': 'root', 'perms': '755', 'orecursive': False, 'precursive': False, } if ('owner' in request.DATA): options['owner'] = request.DATA['owner'] if ('group' in request.DATA): options['group'] = request.DATA['group'] else: options['group'] = options['owner'] if ('orecursive' in request.DATA): options['orecursive'] = True if ('perms' in request.DATA): options['perms'] = request.DATA['perms'] if ('precursive' in request.DATA): options['precursive'] = True share.owner = options['owner'] share.group = options['group'] share.perms = options['perms'] share.save() mnt_pt = ('%s%s' % (settings.MNT_PT, share.name)) force_mount = False if (not is_share_mounted(share.name)): pool_device = Disk.objects.filter(pool=share.pool)[0].name mount_share(share.subvol_name, pool_device, mnt_pt) force_mount = True chown(mnt_pt, options['owner'], options['group'], options['orecursive']) chmod(mnt_pt, options['perms'], options['precursive']) if (force_mount is True): umount_root(mnt_pt) return Response(ShareSerializer(share).data) except RockStorAPIException: raise except Exception, e: handle_exception(e, request)
def post(self, request): try: sname = request.DATA['sname'] if (Share.objects.filter(name=sname).exists()): e_msg = ('Share with name: %s already exists.' % sname) handle_exception(Exception(e_msg), request) pool_name = request.DATA['pool'] size = int(request.DATA['size']) #in KB self._validate_share_size(request, size) pool = None try: pool = Pool.objects.get(name=pool_name) except: e_msg = ('Pool with name: %s does not exist.' % pool_name) handle_exception(Exception(e_msg), request) disk = None try: disk = Disk.objects.filter(pool=pool)[0] except: e_msg = ('Pool with name: %s does not have any disks in it.' % pool_name) handle_exception(Exception(e_msg), request) add_share(pool_name, disk.name, sname) qgroup_id = self._update_quota(pool_name, disk.name, sname, size) s = Share(pool=pool, qgroup=qgroup_id, name=sname, size=size, subvol_name=sname) s.save() return Response(ShareSerializer(s).data) except RockStorAPIException: raise except Exception, e: handle_exception(e, request)
def create_clone(share, new_name, request, logger, snapshot=None): # if snapshot is None, create clone of the share. # If it's not, then clone it. if (re.match(settings.SHARE_REGEX + '$', new_name) is None): e_msg = ('Clone name is invalid. It must start with a letter and can ' 'contain letters, digits, _, . and - characters.') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=new_name).exists()): e_msg = 'Another share with name ({}) already exists.'.format(new_name) handle_exception(Exception(e_msg), request) if (Snapshot.objects.filter(share=share, name=new_name).exists()): e_msg = ('Snapshot with name ({}) already exists for the ' 'share ({}). Choose a different name.').format(new_name, share.name) handle_exception(Exception(e_msg), request) try: share_name = share.subvol_name snap = None if (snapshot is not None): snap = snapshot.real_name add_clone(share.pool, share_name, new_name, snapshot=snap) snap_id = share_id(share.pool, new_name) qgroup_id = ('0/%s' % snap_id) pqid = qgroup_create(share.pool) new_share = Share(pool=share.pool, qgroup=qgroup_id, pqgroup=pqid, name=new_name, size=share.size, subvol_name=new_name) new_share.save() if pqid is not PQGROUP_DEFAULT: update_quota(new_share.pool, pqid, new_share.size * 1024) share_pqgroup_assign(pqid, new_share) # Mount our new clone share. mnt_pt = '{}{}'.format(settings.MNT_PT, new_name) mount_share(new_share, mnt_pt) return Response(ShareSerializer(new_share).data) except Exception as e: handle_exception(e, request)
def post(self, request): # qgroup notes for shares. we need to create a qgroup prior to share # creation. qgroup ids 0/<subvol_id> automatically get created when a # subvolume(i.e., a Share or a Snapshot) is created. So let's create a # new qgroup: 2015/<some_number> whenever a Share is # created. <some_number> starts from 1 and is incremented as more # Shares are created. So, for the very first Share in a pool, it's # qgroup will be 1/1. 2015 is arbitrarily chose. # Before creating a new Share, we create the qgroup for it. And during # it's creation, we assign this qgroup to it. During it's creation a # 0/x qgroup will automatically be created, but it will become the # child of our explicitly-created qgroup(2015/x). # We will set the qgroup limit on our qgroup and it will enforce the # quota on every subvolume(i.e., Share and Snapshot) in that qgroup. # When a Share is deleted, we need to destroy two qgroups. One is it's # auto 0/x qgroup and the other is our explicitly-created 2015/y # qgroup. with self._handle_exception(request): pool_name = request.data.get('pool', None) try: pool = Pool.objects.get(name=pool_name) except: e_msg = 'Pool ({}) does not exist.'.format(pool_name) handle_exception(Exception(e_msg), request) compression = self._validate_compression(request) size = self._validate_share_size(request, pool) sname = request.data.get('sname', None) if ((sname is None or re.match('%s$' % settings.SHARE_REGEX, sname) is None)): e_msg = ('Invalid characters in share name. Following are ' 'allowed: letter(a-z or A-Z), digit(0-9), ' 'hyphen(-), underscore(_) or a period(.).') handle_exception(Exception(e_msg), request) if (len(sname) > 254): # btrfs subvolume names cannot exceed 254 characters. e_msg = ('Share name length cannot exceed 254 characters.') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=sname).exists()): # Note e_msg is consumed by replication/util.py create_share() e_msg = ('Share ({}) already exists. Choose a ' 'different name.').format(sname) handle_exception(Exception(e_msg), request) if (Pool.objects.filter(name=sname).exists()): e_msg = ('A pool with this name ({}) exists. Share ' 'and pool names must be distinct. Choose ' 'a different name.').format(sname) handle_exception(Exception(e_msg), request) replica = False if ('replica' in request.data): replica = request.data['replica'] if (type(replica) != bool): # TODO: confirm this 'type' call works as format parameter. e_msg = ('Replica must be a boolean, ' 'not ({}).').format(type(replica)) handle_exception(Exception(e_msg), request) pqid = qgroup_create(pool) add_share(pool, sname, pqid) qid = qgroup_id(pool, sname) s = Share(pool=pool, qgroup=qid, pqgroup=pqid, name=sname, size=size, subvol_name=sname, replica=replica, compression_algo=compression) # The following pool.save() was informed by test_share.py pool.save() s.save() if pqid is not PQGROUP_DEFAULT: update_quota(pool, pqid, size * 1024) share_pqgroup_assign(pqid, s) mnt_pt = '%s%s' % (settings.MNT_PT, sname) if not s.is_mounted: mount_share(s, mnt_pt) if (compression != 'no'): set_property(mnt_pt, 'compression', compression) return Response(ShareSerializer(s).data)
def create_repclone(share, request, logger, snapshot): """ Variant of create_clone but where the share already exists and is to be supplanted by a snapshot which is effectively moved into the shares prior position, both in the db and on the file system. This is achieved thus: Unmount target share - (via remove_share()). Btrfs subvol delete target share (via remove_share()). Remove prior target share mount point (dir). Move snap source to target share's former location (becomes share on disk). Update existing target share db entry with source snap's qgroup / usage. Remove source snap's db entry: updated share db entry makes it redundant. Remount share (which now represents the prior snap's subvol relocated). :param share: Share object to be supplanted :param request: :param logger: Logger object to reference :param snapshot: Source snapshot/quirk share object to supplant target. :return: response of serialized share (in it's updated form) """ try: logger.info("Supplanting share ({}) with " "snapshot ({}).".format(share.name, snapshot.name)) # We first strip our snapshot.name of any path as when we encounter the # initially created receive subvol it is identified as a share with a # snapshots location as it's subvol name (current quirk of import sys). # E.g. first receive subvol/share-in-snapdir name example: # ".snapshots/C583C37F-...1712B_sharename/sharename_19_replication_1". # Subsequent more regular snapshots (in db as such) are named thus: # "sharename_19_replication_2" or "sharename_19_replication_2" and on. # The 19 in the above names is the generation of the replication task. # # Normalise source name across initial quirk share & subsequent snaps. source_name = snapshot.name.split("/")[-1] # Note in the above we have to use Object.name for polymorphism, but # our share is passed by it's subvol (potential fragility point). snap_path = "{}/.snapshots/{}/{}".format(share.pool.mnt_pt, share.name, source_name).replace( "//", "/") # e.g. for above: /mnt2/poolname/.snapshots/sharename/snapname # or /.snapshots/sharename/snapname for system pool shares share_path = ("{}/{}".format(share.pool.mnt_pt, share.name)).replace("//", "/") # e.g. for above: /mnt2/poolname/sharename or /sharename for system pool shares # Passed db snap assured by caller but this does not guarantee on disk. if not is_subvol(snap_path): raise Exception("Subvol with path ({}) does not exist. Aborting " "replacement of share with path ({}).".format( snap_path, share_path)) # unmounts and then subvol deletes our on disk share remove_share(share.pool, share.name, PQGROUP_DEFAULT) # Remove read only flag on our snapshot subvol set_property(snap_path, "ro", "false", mount=False) # Ensure removed share path is clean, ie remove mount point. run_command(["/usr/bin/rm", "-rf", share_path], throw=False) # Now move snapshot to prior shares location. Given both a share and # a snapshot are subvols, we effectively promote the snap to a share. logger.info( "Moving snapshot ({}) to prior share's pool location ({})".format( snap_path, share_path)) shutil.move(snap_path, share_path) # This should have re-established our just removed subvol. # Supplant share db info with snap info to reflect new on disk state. share.qgroup = snapshot.qgroup share.rusage = snapshot.rusage share.eusage = snapshot.eusage share.save() # delete our now redundant snapshot/quirky share db entry snapshot.delete() # update our share's quota update_quota(share.pool, share.pqgroup, share.size * 1024) # mount our newly supplanted share # We independently mount all shares, data pool or system pool, in /mnt2/name mnt_pt = "{}{}".format(settings.MNT_PT, share.name) mount_share(share, mnt_pt) return Response(ShareSerializer(share).data) except Exception as e: handle_exception(e, request)
def post(self, request): #qgroup notes for shares. we need to create a qgroup prior to share #creation. qgroup ids 0/<subvol_id> automatically get created when a #subvolume(i.e., a Share or a Snapshot) is created. So let's create a #new qgroup: 2015/<some_number> whenever a Share is #created. <some_number> starts from 1 and is incremented as more Shares #are created. So, for the very first Share in a pool, it's qgroup will #be 1/1. 2015 is arbitrarily chose. #Before creating a new Share, we create the qgroup for it. And during #it's creation, we assign this qgroup to it. During it's creation a 0/x #qgroup will automatically be created, but it will become the child of #our explicitly-created qgroup(2015/x). #We will set the qgroup limit on our qgroup and it will enforce the #quota on every subvolume(i.e., Share and Snapshot) in that qgroup. #When a Share is deleted, we need to destroy two qgroups. One is it's #auto 0/x qgroup and the other is our explicitly-created 2015/y qgroup. with self._handle_exception(request): pool_name = request.data.get('pool', None) try: pool = Pool.objects.get(name=pool_name) except: e_msg = ('Pool(%s) does not exist.' % pool_name) handle_exception(Exception(e_msg), request) compression = self._validate_compression(request) size = self._validate_share_size(request, pool) sname = request.data.get('sname', None) if ((sname is None or re.match('%s$' % settings.SHARE_REGEX, sname) is None)): e_msg = ('Share name must start with a alphanumeric(a-z0-9) ' 'character and can be followed by any of the ' 'following characters: letter(a-z), digits(0-9), ' 'hyphen(-), underscore(_) or a period(.).') handle_exception(Exception(e_msg), request) if (len(sname) > 254): #btrfs subvolume names cannot exceed 254 characters. e_msg = ('Share name length cannot exceed 254 characters') handle_exception(Exception(e_msg), request) if (Share.objects.filter(name=sname).exists()): e_msg = ('Share(%s) already exists. Choose a different name' % sname) handle_exception(Exception(e_msg), request) if (Pool.objects.filter(name=sname).exists()): e_msg = ( 'A Pool with this name(%s) exists. Share and Pool names ' 'must be distinct. Choose a different name' % sname) handle_exception(Exception(e_msg), request) disk = Disk.objects.filter(pool=pool)[0] replica = False if ('replica' in request.data): replica = request.data['replica'] if (type(replica) != bool): e_msg = ('replica must be a boolean, not %s' % type(replica)) handle_exception(Exception(e_msg), request) pqid = qgroup_create(pool) add_share(pool, sname, pqid) qid = qgroup_id(pool, sname) update_quota(pool, pqid, size * 1024) s = Share(pool=pool, qgroup=qid, pqgroup=pqid, name=sname, size=size, subvol_name=sname, replica=replica, compression_algo=compression) s.save() mnt_pt = '%s%s' % (settings.MNT_PT, sname) if (not is_share_mounted(sname)): mount_share(s, mnt_pt) if (compression != 'no'): set_property(mnt_pt, 'compression', compression) return Response(ShareSerializer(s).data)