def list_gateways_by_user(email, **q_opts): caller_user = _check_authenticated(q_opts) # user must exist user = read_user(email) if user == None: raise Exception("No such user '%s'" % email) # only admin can list other users' gateways if caller_user.owner_id != user.owner_id and not caller_user.is_admin: raise Exception("User '%s' is not sufficiently privileged" % caller_user.email) return Gateway.ListAll({"Gateway.owner_id ==": user.owner_id}, **q_opts)
def _remove_user_from_volume_helper(owner_id, volume_id): # helper function for remove_user_from_volume, to be run deferred. def _remove_gateway(gw): Gateway.Delete(gw.g_id) return None Gateway.ListAll( { "Gateway.owner_id ==": owner_id, "Gateway.volume_id ==": volume_id }, map_func=_remove_gateway, projection=['g_id'])
def list_gateways_by_volume(volume_name_or_id, **q_opts): caller_user = _check_authenticated(q_opts) # volume must exist volume = read_volume(volume_name_or_id) if volume == None or volume.deleted: raise Exception("No such Volume '%s'" % volume_name_or_id) # only admin can list gateways of volumes she doesn't own if volume.owner_id != caller_user.owner_id and not caller_user.is_admin: raise Exception("User '%s' is not sufficiently privileged" % caller_user.email) return Gateway.ListAll({"Gateway.volume_id ==": volume.volume_id}, **q_opts)
def list_gateways_by_user_and_volume(email, volume_name_or_id, **q_opts): caller_user = _check_authenticated(q_opts) user, volume = _read_user_and_volume(email, volume_name_or_id) # user and volume must exist if user is None: raise Exception("No such user '%s'" % email) if volume is None or volume.deleted: raise Exception("No such Volume '%s'" % email) # only admin can list other users' gateways if caller_user.owner_id != user.owner_id and not caller_user.is_admin: raise Exception("User '%s' is not sufficiently privileged" % caller_user.email) return Gateway.ListAll( { "Gateway.owner_id ==": user.owner_id, "Gateway.volume_id ==": volume.volume_id }, **q_opts)
def update_gateway(g_name_or_id, **fields): # NOTE: the UpdateAPIGuard ensures that the caller user exists, # and that the user is either admin or the owner of this gateway. # We only need to read the volume and gateway to call Volume.Reversion # gateway must exist...(defensive check) gateway = read_gateway(g_name_or_id) if gateway == None: raise Exception("No such Gateway '%s'" % g_name_or_id) volume = read_volume(gateway.volume_id) # volume must exist...(defensive check) if volume == None or volume.deleted: raise Exception("No volume with ID '%s'" % gateway.volume_id) rc = Gateway.Update(g_name_or_id, **fields) if rc: storagetypes.deferred.defer(Volume.Reversion, volume.volume_id) return rc
def set_gateway_caps(g_name_or_id, caps): # NOTE: the UpdateAPIGuard ensures that the user exists, and that the user # is either an admin or the owner of this Gateway. # we only read the user and volume again since we have to call Volume.Reversion # gateway must exist...(defensive check) gateway = read_gateway(g_name_or_id) if gateway == None: raise Exception("No such Gateway '%s'" % g_name_or_id) volume = read_volume(gateway.volume_id) # volume must exist...(defensive check) if volume == None or volume.deleted: raise Exception("No volume with ID '%s'" % gateway.volume_id) rc = Gateway.SetCaps(g_name_or_id, caps) if rc: # reversion volume cert storagetypes.deferred.defer(Volume.Reversion, volume.volume_id) return rc
def protobuf_gateway_cert_manifest(self, manifest, include_cert=None, sign=True): """ Generate a specially-crafted manifest protobuf, which a gateway can use to learn the IDs and types of all gateways in the Volume, as well as their certs' versions. """ manifest.volume_id = self.volume_id manifest.coordinator_id = 0 manifest.file_id = 0 manifest.owner_id = 0 manifest.file_version = self.cert_version manifest.mtime_sec = 0 manifest.mtime_nsec = 0 manifest.fent_mtime_sec = 0 manifest.fent_mtime_nsec = 0 sz = 0 # query certificate versions, types, and caps of all gateways that need to be trusted listing = Gateway.ListAll( { "Gateway.volume_id ==": self.volume_id, "Gateway.need_cert ==": True }, projection=["g_id", "gateway_type", "cert_version", "caps"]) # if the caller wants to include a particular gateway's cert, do so has_included_cert = False for gateway_metadata in listing: cert_block = manifest.block_url_set.add() self.protobuf_gateway_cert_manifest_record( cert_block, gateway_metadata.g_id, gateway_metadata.gateway_type, gateway_metadata.caps, gateway_metadata.cert_version) logging.info( "cert block: (%s, %s, %s, %x)" % (gateway_metadata.gateway_type, gateway_metadata.g_id, gateway_metadata.cert_version, gateway_metadata.caps)) sz += 1 if gateway_metadata.g_id == include_cert: has_included_cert = True if not has_included_cert and include_cert is not None: # get this gateway's cert as well gw = Gateway.Read(include_cert) if gw is not None: cert_block = manifest.block_url_set.add() self.protobuf_gateway_cert_manifest_record( cert_block, gw.g_id, gw.gateway_type, gw.caps, gw.cert_version) logging.info("cert block (included for %s): (%s, %s, %s, %x)" % (include_cert, gw.gateway_type, gw.g_id, gw.cert_version, gw.caps)) sz += 1 manifest.size = sz manifest.signature = "" if sign: data = manifest.SerializeToString() sig = self.sign_message(data) manifest.signature = sig return
def delete_gateway(g_id): # TODO: when deleting an AG, delete all of its files and directories as well return Gateway.Delete(g_id)
def _remove_gateway(gw): Gateway.Delete(gw.g_id) return None
def list_gateways_by_host(hostname, **q_opts): return Gateway.ListAll({"Gateway.host ==": hostname}, **q_opts)
def list_gateways(attrs=None, **q_opts): return Gateway.ListAll(attrs, **q_opts)
def read_gateway(g_name_or_id): return Gateway.Read(g_name_or_id)
def create_gateway(volume_id, email, gateway_type, gateway_name, host, port, **kwargs): if "encryption_password" in kwargs.keys(): del kwargs['encryption_password'] # verify gateway type... if gateway_type not in [GATEWAY_TYPE_UG, GATEWAY_TYPE_RG, GATEWAY_TYPE_AG]: raise Exception("Unrecognized Gateway type %s" % gateway_type) gateway_type_str = GATEWAY_TYPE_TO_STR[gateway_type] caller_user = _check_authenticated(kwargs) # user and volume must both exist user, volume = _read_user_and_volume(email, volume_id) if user == None: raise Exception("No such user '%s'" % email) if (volume == None or volume.deleted): raise Exception("No such volume '%s'" % volume_id) # if the caller user doesn't own this Volume (or isn't an admin), (s)he must have a valid access request if not caller_user.is_admin and caller_user.owner_id != volume.owner_id: # caller user must be the same as the user if caller_user.owner_id != user.owner_id: raise Exception("Caller can only create gateways for itself.") # if the volume is not public, then there needs to be a volume access request that is granted to this user. if not volume.private: # check access status access_request = VolumeAccessRequest.GetAccess( user.owner_id, volume.volume_id) if access_request == None: # user has not been given permission to access this volume raise Exception( "User '%s' is not allowed to access Volume '%s'" % (caller_user.email, volume.name)) if access_request.status != VolumeAccessRequest.STATUS_GRANTED: # user has not been given permission to create a gateway here raise Exception( "User '%s' is not allowed to create a Gateway in Volume '%s'" % (caller_user.email, volume.name)) else: # verify caps requested_caps = kwargs.get("caps", None) if requested_caps is not None and requested_caps != access_request.gateway_caps: raise Exception( "User '%s' is not allowed to set Gateway capabilities '%s'" % requested_caps) # verify the caller is allowed to create this kind of gateway if not access_request.is_gateway_type_allowed(gateway_type): raise Exception( "User '%s' is not allowed to create %s Gateways" % (gateway_type_str)) # user is allowed to create this gateway in this Volume... # verify quota gateway_quota = user.get_gateway_quota(gateway_type) if gateway_quota == 0: gateway_type_str = GATEWAY_TYPE_TO_STR[gateway_type] raise Exception("User '%s' cannot own %s Gateways" % (email, gateway_type_str)) if gateway_quota > 0: gateway_ids = list_gateways_by_user(user.email, caller_user=user, keys_only=True) if len(gateway_ids) > gateway_quota: gateway_type_str = GATEWAY_TYPE_TO_STR[gateway_type] raise Exception( "User '%s' has exceeded quota (%s) for %s Gateways" % (email, gateway_quota, gateway_type_str)) gateway_key = Gateway.Create(user, volume, gateway_type=gateway_type, name=gateway_name, host=host, port=port, **kwargs) gw = gateway_key.get() # reversion volume cert? if gw is not None: storagetypes.deferred.defer(Volume.Reversion, volume_id) return gw
def delete_gateway(g_id, **kw): # TODO: garbage-collect gateways... ret = Gateway.Delete(g_id) return {'result': ret}
def list_gateways_by_host(hostname, **q_opts): return Gateway.ListAll( { "Gateway.host ==": hostname, "Gateway.deleted ==": False }, **q_opts)
if volume.private: # only volume owner or admin can create gateways in private volumes if not caller_user.is_admin and caller_user.owner_id != volume.owner_id: raise Exception( "User '%s' is not allowed to create gateways for '%s'" % (caller_user.email, volume.name)) # if this is an archive volume, then there can be no other writers (DEPRECATED) if volume.archive and ( gateway_cert.caps & (GATEWAY_CAP_WRITE_DATA | GATEWAY_CAP_WRITE_METADATA)): writer_gateways_qry = Gateway.ListAll( { "Gateway.need_cert ==": True, 'Gateway.volume_id ==': volume_id }, keys_only=True, query_only=True) if writer_gateways_qry.count() > 0: # there's already a writer raise Exception("Archive volume '%s' already has a writer" % (volume.name)) # sanity check: name can't be numeric tmp = None try: tmp = int(gateway_name) except: pass