0

I'm trying to create a storage quota on our Isilon cluster via the OneFS REST API. I'm using a class library from a former EMC engineer and added my own method to create a quota but cannot figure out why the 400 error is being returned. This is currently being sent via a simple console application and the same payload and URL works without any issues in Postman. I'd really like to continue to using and building out this library as a bunch of work has already been done. Any help or insight would be appreciated.

My call to my CreateQuota method from Main

 static void Main(string[] args)
    {

        //DisplayQuotas();

        bool qcontainer = false;
        bool qenforced = false;
        bool qincludesnaps = false;
        bool qthresincludeoverhead = false;
        string qtype = "directory";
        string qpath = "/path/to/myquota/diectory";         
        SmartQuotas quotas = new SmartQuotas(service);
        quotas.CreateQuota(qcontainer, qenforced, qincludesnaps, qthresincludeoverhead, qtype, qpath);

    }

The CreateQuota method that I added and it's leveraging DataMemberAttribute from another class - this is modeled after the existing method to create an SMB share.

public Quota CreateQuota(bool container, bool enforced, bool include_snapshots, bool thresholds_include_overhead, string type, string path)
    {
        Quota quota = new Quota();
        quota.Container = container;
        quota.Enforced = enforced;
        quota.IncludeSnapshots = include_snapshots;
        quota.ThresholdsIncludeOverhead = thresholds_include_overhead;
        quota.Type = type;
        quota.Path = path;
       
        Post<Quota>("/platform/1/quota/quotas", quota);
        
        //quota = GetQuotas()[0];

        return quota;
    }

This is the Post method and it's using DataContractSerializer which I feel like is part of my problem. I'm just not sure why the body I'm sending wouldn't be parsed correctly and also having trouble deserializing to see what my request would look like.

 protected void Post<T>(string resource, T body)
    {
        try
        {
            // Create a web request object pointing to the Isilon server and Resource String
            HttpWebRequest request = _Service.CreateRequest(resource);
            request.Method = "POST";

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            serializer.WriteObject(request.GetRequestStream(), (T)body);

            // Attempt at reading the stream but throws System.NotSupportedException
            //T t2 = (T)serializer.ReadObject(request.GetRequestStream());
     
            // Send the request to the Isilon cluster and get there response
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            response.Close();


        }
        catch(WebException e)
        {
            Console.WriteLine("This is the WebException from a POST attempt: " + e.Message);
            if(e.Status == WebExceptionStatus.ProtocolError)
            {
                Console.WriteLine("Status Code: {0}", ((HttpWebResponse)e.Response).StatusCode);
                Console.Write("Status Description: {0}", ((HttpWebResponse)e.Response).StatusDescription);
            }
        }

    }

This is a slimmed down version of the DataContract class as well which is visible on the Git repo I linked to.

[DataContract]
public class Quota
{
    // Enables the SMB shares using the quota directory to see the quota threshold as the share size.
    [DataMember(Name = "container", EmitDefaultValue = false)]
    public bool Container;

    // True if the quota provides enforcement, otherwise an accounting quota
    [DataMember(Name = "enforced", EmitDefaultValue = false)]
    public bool Enforced;

    // True if the quota governs snapshot data as well as head data.
    [DataMember(Name = "include_snapshots", EmitDefaultValue = false)]
    public bool IncludeSnapshots;

    // True if the thresholds apply to the data plus file system overhead that is required to store the data
    // (such as physical useage)
    [DataMember(Name = "thresholds_include_overhead", EmitDefaultValue = false)]
    public bool ThresholdsIncludeOverhead;

            // Type of quota - User, group, directory
    [DataMember(Name = "type", EmitDefaultValue = false)]
    public string Type;

    // OneFS path
    [DataMember(Name = "path", EmitDefaultValue = false)]
    public string Path;

}
JLudt
  • 9
  • 6

1 Answers1

0

The answer turned out to be rather straight forward - the schema for the threshold object has a nested value, which wasn't being formed properly. I ended up using RestSharp to make this call from scratch myself as well as taking a closer look at the OneFS API documentation both of which ultimately helped me see what was going on here.

JLudt
  • 9
  • 6