File storage using Openstack Swift

Damian Kolaska
3 min readMay 23, 2021

This story is about my experience creating file storage web app for the University course.

Our task was to create an app which could handle downloading and uploading large files. As a file storage we chose Openstack Swift.

What is Openstack Swift

According to documentation “Swift is a highly available, distributed, eventually consistent object/blob store. Organizations can use Swift to store lots of data efficiently, safely, and cheaply.”

Besides all of those great qualities lies a problem. Swift is really cumbersome to administer. Its architecture is split into multiple nodes. All of which require configuration. So if your organization is small it might not be a great idea to use it. You might be better off just storing files in the server’s filesystem.

Setting up Swift

Swift’s documentation is very extensive, but because of that it is also really hard to start using the service. You can deploy your first instance following this tutorial. https://docs.openstack.org/swift/latest/deployment_guide.html

The tutorial is quite long and there isn’t really a way to test things until you completely finish them. That’s why I think it is better to start with a Docker image.

Start a container (use port 8090 as 8080 can collide with other services)

docker run -d -p 8090:8080 --name openstack-swift -v -t dockerswiftaio/docker-swift

Application logs are in /var/log/swift/. Don’t get surprised if they get big pretty quickly. Our logs grew to about 18GB after 2–3 weeks of runtime.

It might happen that the container will not work correctly. In our case there was an issue with directory permissions. It manifested itself in such lines in /var/log/swift/all.log

Permission denied: ‘/srv/1/node/sdb1/objects/auditor_status_ALL.json’)

To fix that we changed the permissions using chown

chown -R swift:swift /swift/nodes/1/sdb1

Here’s the guide showing how to correctly set permissions for docker volumes https://medium.com/@nielssj/docker-volumes-and-file-system-permissions-772c1aee23ca

Working with Swift API

You can communicate with Swift service directly, using their REST API https://docs.openstack.org/api-ref/object-store/index.html

# Authenticate
curl -v -H 'X-Storage-User: test:tester' -H 'X-Storage-Pass: testing' http://127.0.0.1:<port>/auth/v1.0
# Response
* About to connect() to 127.0.0.1 port 8080 (#0)
* Trying 127.0.0.1... connected
> GET /auth/v1.0 HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: 127.0.0.1:8080
> Accept: */*
> X-Storage-User: test:tester
> X-Storage-Pass: testing
>
< HTTP/1.1 200 OK
< X-Storage-Url: http://127.0.0.1:8080/v1/AUTH_test
< X-Auth-Token: AUTH_tk246b80e9b72a42e68a76e0ff2aaaf051
< Content-Type: text/html; charset=UTF-8
< X-Storage-Token: AUTH_tk246b80e9b72a42e68a76e0ff2aaaf051
< Content-Length: 0
< Date: Mon, 28 Oct 2013 22:48:51 GMT
<
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0
# You get a token and an url from the response
export URL=http://127.0.0.1:8080/v1/AUTH_test
export TOKEN=AUTH_tk246b80e9b72a42e68a76e0ff2aaaf051
# Create container named testcontainer
curl -X PUT -i -H "X-Auth-Token: $TOKEN" $URL/testcontainer
# Upload a file to Swift
curl -X PUT -i -H "X-Auth-Token: $TOKEN" -T file.mkv $URL/testcontainer/testobject
# Download file from Swift
curl -X GET -H "X-Auth-Token: $TOKEN" -o retrieved_file.mkv $URL/testcontainer/testobject

As you can see using the API isn’t so hard, but there is a better option. You can use JOSS, a library specifically for communicating with Openstack Swift http://joss.javaswift.org/

private final Account loginToSwift() {
return new AccountFactory()
.setAuthUrl(SWIFT_STORAGE_URL)
.setUsername(SWIFT_STORAGE_USER)
.setPassword(SWIFT_STORAGE_PWD)
.setTenantName(SWIFT_STORAGE_TENANT)
.setAuthenticationMethod(AuthenticationMethod.BASIC)
.createAccount();
}
private final Container getContainer(String containerName) {
final Container container = loginToSwift().getContainer(containerName);
if (!container.exists()) {
container.create();
}
return container;
}
public String uploadFile(byte[] newFile, String containerName) {
final String swiftID = generateID();
var container = getContainer(containerName);
final StoredObject newFileObject = container.getObject(swiftID);
if (!newFileObject.exists()) {
newFileObject.uploadObject(newFile);
}
return swiftID;
}
public byte[] download(String swiftID, String containerName) {
var container = getContainer(containerName);
var storedObject = container.getObject(swiftID);
if (!storedObject.exists()) return null;
return storedObject.downloadObject();
}

Explanation

loginToSwift
As you can imagine it logs into Swift.
Parameters:
* AuthUrl : address of swift instance, e.g. http://localhost:8096/auth/v1.0
* Username : username you want to login with
* Password : password for provided username
* Tenant : this one is a bit tricky. It’s just a project name.

getContainer
It first logs into Swift then calls getContainer with container name SWIFT_CONTAINER_NAME (It doesn’t have to be a constant. You can have many containers). You can see that we then use exists function to check if the container is created. Methods in JOSS generally don’t return nulls. Instead you get an empty handle.

upload
download
Once again we use the same pattern. Get container. Retrieve object handle. Perform operation.

I hope that after all of this you’re ready to start you journey with Openstack Swift.

--

--