Introduction
This article dives a little deeper into using the Isilon OneFS 7.2 REST API using C# .NET. It focuses on namespace (File/Folder) access using the API. This article will cover how to enable file system access, create access points, create users and access control lists (ACLs), and basic file system queries.
Background
I was working on several automation and visualization applications for EMC's Isilon scale out NAS platform and couldn't find much information about how to access the API in .NET. In my first article, EMC Isilon OneFS REST API using C# .NET, I covered the basics about how to connect to, authenticate, and query data from an Isilon cluster, as well as basic JSON de-serialization of the responses into .NET objects. Please refer to my previous article to get started.
File System Access
Accessing files and folders on an Isilon cluster using the OneFS API is similar to how you would access files and folders using SMB or NFS protocols. At the base, you need an access point, which is similar to a CIFS share or an NFS mount point. Starting out, only the root user will have access to the file system, so you will need to use the root account to create users, access points, and grant access.
Get Namespaces
Authenticating against the cluster using the root account (root@clustername), you can use the /namespace/
resource to obtain a list of all access points that root has access to. In the beginning, it should only be the /ifs/
access point.
First, we want to authenticate to the cluster using the root credentials (see the previous article on how to obtain a session cookie). Afterwards, we will want to do a HTTP GET request to the /namespace/
resource to get a list of all access points.
ResourceString = "/namespace/";
request = (HttpWebRequest)WebRequest.Create(IsilonServerAddress + ResourceString);
request.Headers.Add("Cookie", cookie);
response = (HttpWebResponse)request.GetResponse();
And here is the json response from this GET
query.
{"namespaces":[{
"name" : "ifs",
"path" : "/ifs"
}
]}
Here are the classes I use to de-serialize the json response into .NET objects.
[DataContract]
public class IsilonNamespaceResponse
{
[DataMember(Name = "namespaces")]
public Namespace[] AccessPoints;
}
[DataContract]
public class Namespace
{
[DataMember(Name = "name", IsRequired = true)]
public string Name;
[DataMember(Name = "path", IsRequired = true)]
public string Path;
}
Finally, we create our .NET object:
DataContractJsonSerializer js =
new DataContractJsonSerializer(typeof(IsilonNamespaceResponse));
IsilonNamespaceResponse members =
(IsilonNamespaceResponse)js.ReadObject(response.GetResponseStream());
foreach(Namespace accessPoint in members.AccessPoints)
{
}
Creating Access Points
In some applications, it may make sense to use the main access point /ifs/
, however this will grant access to the entire OneFS file system, so it is highly recommended that applications written to use the API for file system access use an alternate access point. To create an access point, you will need to preform an HTTP PUT
request to the /namespace/
resource. The format of the request will be /namespace/*NewAccessPointName*
<name access="" create="" new="" of="" point="" to="">, and the body of the request will be a JSON object with the absolute path within the OneFS file system to the access point.
The request should look like this:
PUT /namespace/accesspoint1 HTTP/1.1 Host my_cluster:8080
Date: Fri, 15 Mar 2013 21:51:50 GMT
Content-Type: text/xml
{
"path": "/ifs/home/"
}
In this case, I want to create an access point called "MyAccessPoint
" and point it to a folder on the OneFS file system called Share1. I have created this folder on my Isilon cluster:
Note: The absolute path on the file system MUST exist before you create an access point using it. Otherwise, the command will return a HTTP 400 message.
To create the access point, first I need a class to represent the json object that we will send to the cluster:
[DataContract]
public class AccessPoint
{
[DataMember(Name = "path")]
public string AbsolutePath;
}
Next, I need to create an instance of this class and give the "path
" property an absolute path into the file system. As well, I need to specify the access point name in the request string. Finally, I need to serialize that object out to the RequestStream
of an HTTP PUT
request object.
string AccessPointName = "MyAccessPoint";
AccessPoint MyAccessPoint = new AccessPoint();
MyAccessPoint.AbsolutePath = "/ifs/Share1";
ResourceString = "/namespace/" + AccessPointName;
request = (HttpWebRequest)WebRequest.Create(IsilonServerAddress + ResourceString);
request.Method = "PUT";
request.ContentType = "text/xml";
request.Headers.Add("Cookie", cookie);
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(AccessPoint));
js.WriteObject(request.GetRequestStream(), MyAccessPoint);
response = (HttpWebResponse)request.GetResponse();
User Access
Now that we have an access point, we'll want to manage the user permissions to that access point. (In other words, don't use the root account for production file system access within your applications!). First, we need to create a user, and unfortunately I don't see a way to do this through the API, though if I find it, I will modify this article. However, you can use the GUI or the CLI to create a user. For instance, using the CLI, use the following command:
isi auth users create user1 --password user1 --home-directory /ifs/ home/user1 --password-expires no
After we have our user created, we can grant those user permissions to that access point. The json object we would need to pass is this:
{
"authoritative":"acl",
"acl":
[{
"trustee":
{
"name":"user1",
"type":"user"
},
"accesstype":"allow",
"accessrights":["file_read"],
"op":"add"
}]
}
First, here are the .NET classes needed to create this json object:
[DataContract]
public class Trustee
{
[DataMember(Name = "name")]
public string UserName;
[DataMember(Name = "type")]
public string UserType;
}
[DataContract]
public class AccessControlList
{
[DataMember(Name = "trustee")]
public Trustee Trustee;
[DataMember(Name = "accesstype")]
public string AccessType;
[DataMember(Name = "accessrights")]
public string[] AccessRights;
[DataMember(Name = "op")]
public string Operation;
}
[DataContract]
public class CreateACL
{
[DataMember(Name = "authoritative")]
public string authoritative = "acl";
[DataMember(Name = "acl")]
public AccessControlList[] acl;
}
Now, we will need to create the ACL, trustee, and request object to pass to the Isilon cluster. You will need to create an HTTP PUT
command, and pass the json object against the Access Point with the following query parameters - acl
, and nsaccess
, which will look like this: "PUT /namespace/
<access_point>?acl&nsaccess=true
" The nsaccess
parameter is used to indicate that the requested operation is on the access point itself, instead of the store path. The value must be set to true
, otherwise the request will behave similarly to a get
or put
operation against the data within the access point.
The following code creates the .NET object that we will use to send to the Isilon cluster:
Trustee trustee = new Trustee();
trustee.UserName = "user1";
trustee.UserType = "user";
AccessControlList acl = new AccessControlList();
acl.Trustee = trustee;
acl.Operation = "add";
acl.AccessType = "allow";
acl.AccessRights = new string[] { "file_read" };
CreateACL createAcl = new CreateACL();
createAcl.acl = new AccessControlList[] { acl };
Now let's pass our object to the Isilon cluster:
string AccessPointName = "MyAccessPoint";
ResourceString = "/namespace/" + AccessPointName + "?acl&nsaccess=true";
request = (HttpWebRequest)WebRequest.Create(IsilonServerAddress + ResourceString);
request.Method = "PUT";
request.ContentType = "application/json";
request.Headers.Add("Cookie", cookie);
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(CreateACL));
js.WriteObject(request.GetRequestStream(), createAcl);
response = (HttpWebResponse)request.GetResponse();
Assuming this succeeds, we can then turn around and do a GET
request against the access point, specifying the acl
& nsaccess=true
parameters to get a list of all ACLs on our access point. In other words, GET /namespace/MyAccessPoint?acl&nsaccess=true
which will return something like this:
{
"acl" :
[
{
"accessrights" : [ "file_read" ]
"accesstype" : "allow",
"inherit_flags" : [],
"trustee" :
{
"id" : "UID:2000",
"name" : "user1",
"type" : "user"
}
}
],
"authoritative" : "acl",
"group" :
{
"id" : "GID:0",
"name" : "wheel",
"type" : "group"
},
"mode" : "0040",
"owner" :
{
"id" : "UID:0",
"name" : "root",
"type" : "user"
}
}
And as you can see, user1
is now granted read only access to the access point.
Directory Operations
Now that our user has access to the access point, there's a lot of things you can do from an API perspective. The basic operation is to request a list of all objects within that access point (Files and Folders). For demonstration, I populated my access point with several documents and folders.
To access the information within the access point, remove the acl
& nsaccess=true
parameters from the query string, and what returns is a list of all the objects within that access point:
{"children":[{
"name" : "Notepad.txt"
}
,{
"name" : "MS Word Document.docx"
}
,{
"name" : "MS Excel Spreadsheet.xlsx"
}
,{
"name" : "MS Power Point Presentation.pptx"
}
,{
"name" : "Folder1"
}
]}
Conclusion
This is an example of how you can use the Isilon OneFS API to do access point, access control, and file system access using .NET. Hope you found this information useful!
History