Using Object Storage

Application Mashup (WireCloud) course @ http://edu.fiware.org

Presenter Notes

Using Object Storage

Introduction

Presenter Notes

Introduction

Object Storage offers persistent storage for binary objects. Objects are stored in named locations known as containers. Containers can be nested thus objects can be stored hierarchically. The main aim of this section is to show an example that allows you to understand how to use this API.

Presenter Notes

Using Object Storage

Adding ObjectStorage support to widgets/operators

Presenter Notes

Adding ObjectStorage support to widgets/operators

If you want to use this feature, first of all you have to modify your config.xml file and add a new Feature named ObjectStorage within Requirements. For example, if you use XML to set up the configuration of your widget, your code should look similar to the following one. Note that we have also added a preference that will be useful to store the KeyStone server URL.

<?xml version='1.0' encoding='UTF-8'?>
<widget xmlns="http://wirecloud.conwet.fi.upm.es/ns/macdescription/1" vendor="Wirecloud" name="objectstorage-test-widget" version="1.0">
  <details>
    <title>Wirecloud Object Storage API test widget</title>
    <authors>aarranz</authors>
    <email>aarranz@conwet.com</email>
    <image>images/catalogue.png</image>
    <smartphoneimage>images/catalogue_iphone.png</smartphoneimage>
    <description>This widget is used to test whether the Object Storage API is usable by widgets</description>
    <doc>doc/index.html</doc>
  </details>
  <requirements>
    <feature name="ObjectStorage"/>
  </requirements>
  <preferences>
    <preference name="keystone_url" type="text" label="Keystone Server" description="Keystone Server where the Object Storage server to use for testing the integration between Wirecloud and the Object Storage GE is registered" default="https://cloud.lab.fiware.org/keystone"/>
  </preferences>
  <wiring/>
  <contents src="test.html" contenttype="text/html" charset="utf-8" useplatformstyle="true"/>
  <rendering height="24" width="6"/>
</widget>

Presenter Notes

Adding ObjectStorage support to widgets/operators

In case you prefer to use RDF, your code should be similar to the following one:

!
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
  xmlns:foaf="http://xmlns.com/foaf/0.1/"
  xmlns:wire="http://wirecloud.conwet.fi.upm.es/ns/widget#"
  xmlns:gr="http://purl.org/goodrelations/v1#"
  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  xmlns:usdl="http://www.linked-usdl.org/ns/usdl-core#"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dcterms="http://purl.org/dc/terms/"
  xmlns:vcard="http://www.w3.org/2006/vcard/ns#"
>
  <wire:Widget rdf:about="http://wirecloud.conwet.fi.upm.es/ns/widget#Wirecloud/objectstorage-test-widget/1.0">
    <dcterms:creator>
      <foaf:Person rdf:nodeID="N2cda3cef67eb47558145c705d0d3b191">
        <foaf:name>aarranz</foaf:name>
      </foaf:Person>
    </dcterms:creator>
    <wire:displayName>Wirecloud Object Storage API test widget</wire:displayName>
    <foaf:page rdf:resource="doc/index.html"/>
    <dcterms:description>This widget is used to test whether the Object Storage API is usable by widgets</dcterms:description>
    <wire:hasPlatformPreference>
      <wire:PlatformPreference rdf:nodeID="Nf5128b00c737420f91385f002c272954">
        <dcterms:description>Keystone Server where the Object Storage server to use for testing the integration between Wirecloud and the Object Storage GE is registered</dcterms:description>
        <rdfs:label>Keystone Server</rdfs:label>
        <wire:index>0</wire:index>
        <wire:type>text</wire:type>
        <dcterms:title>keystone_url</dcterms:title>
        <wire:default>https://cloud.lab.fiware.org/keystone</wire:default>
      </wire:PlatformPreference>
    </wire:hasPlatformPreference>
    <wire:hasImageUri rdf:resource="images/catalogue.png"/>
    <usdl:versionInfo>1.0</usdl:versionInfo>
    <dcterms:title>objectstorage-test-widget</dcterms:title>
    <vcard:addr>
      <vcard:Work rdf:nodeID="N353ea6f0c6c24daf8e3e2ba8b1b6396c">
        <vcard:email>aarranz@conwet.com</vcard:email>
      </vcard:Work>
    </vcard:addr>
    <usdl:hasProvider>
      <gr:BusinessEntity rdf:nodeID="Naf20bf95bb5d4a6484f501744b75deb4">
        <foaf:name>Wirecloud</foaf:name>
      </gr:BusinessEntity>
    </usdl:hasProvider>
    <wire:hasPlatformWiring>
      <wire:PlatformWiring rdf:nodeID="Na67dd8db508d48338034a1f14ab4f2c9"/>
    </wire:hasPlatformWiring>
    <usdl:utilizedResource>
      <usdl:Resource rdf:about="test.html">
        <wire:usePlatformStyle>true</wire:usePlatformStyle>
      </usdl:Resource>
    </usdl:utilizedResource>
    <wire:hasPlatformRendering>
      <wire:PlatformRendering rdf:nodeID="Nb55500a19f324a88bc5eff01d3d0bd8d">
        <wire:renderingHeight>24</wire:renderingHeight>
        <wire:renderingWidth>6</wire:renderingWidth>
      </wire:PlatformRendering>
    </wire:hasPlatformRendering>

    <!-- Here we add the Feature -->
    <wire:hasRequirement>
      <wire:Feature rdf:nodeID="N2cdd6eec5a4c43ad8cd68d09f51c100c">
        <rdfs:label>ObjectStorage</rdfs:label>
      </wire:Feature>
    </wire:hasRequirement>
    <wire:hasiPhoneImageUri rdf:resource="images/catalogue_iphone.png"/>
  </wire:Widget>
</rdf:RDF>

Presenter Notes

Using Object Storage

Connecting with the KeyStone Server

Presenter Notes

Connecting with the KeyStone Server

To start using the ObjectStorage, first you have to set up the connection with the KeyStone server. To do so, you should create a new KeystoneAPI:

var keystone = new KeystoneAPI(url, options)

See the ObjectStorage Javascript API documentation for the full list of supported options but, as summary, the url is the ObjectStorage Server location. Also, if you are connecting to a ObjectStorage instance using the IdM authentication, you will need to pass the required authentication credentials. This can be accomplished in two ways:

  • Making use of the token option and passing directly the required Authentication header
  • Making use of the use_user_fiware_token option to make the ObjectStorage use the token obtained by WireCloud from the IdM

Presenter Notes

Connecting with the KeyStone Server

This example shows you how to connect with the KeyStone server using the resources available in the FIWARE Testbed. Note that the Keystone URL used is the one obtained from the preferences:

var keystone = new KeystoneAPI(MashupPlatform.prefs.get('keystone_url'), {
    use_user_fiware_token: true
});

Presenter Notes

Using Object Storage

Getting all the available tenants for the users

Presenter Notes

Getting all the available tenants for the users

Once that you are connected with the KeyStone server, you have to take into account is that a user can use several tenants to store the information. To get the list of available tenants for a user, you can use the getTenants function:

keystone.getTenants([options])

The options argument allows you to set two callbacks:

  • onSuccess is called when the request finishes successfully. This function will receive a dictionary with the field tenants that contains all the available tenants for the user that make the request
  • onFailure is called when the request finish with errors

Presenter Notes

Getting all the available tenants for the users

In the following example, we call the function with both callbacks. If the request finish successfully, we will show the id of the first available tenant. Otherwise, we will show a message error:

keystone.getTenants({
    onSuccess: function(data) {
        document.getElementById('tenantId').textContent = data.tenants[0].id;
    },
    onFailure: function () {
        document.getElementById('tenantId').textContent = 'Fail';
    }
});

Presenter Notes

Using Object Storage

Getting the authentication token

Presenter Notes

Getting the authentication token

When you have selected the tenant that you want to use, you must get an authentication token using the getAuthToken function:

keystone.getAuthToken([options])

options argument include the following fields:

  • tenantName: name of the tenant to be associated to the generated token. Both the tenantId and tenantName attributes are optional, but should not be specified together
  • tenantId: The id of the tenant to be associated to the generated token. Both the 'tenantId' and 'tenantName' attributes are optional, but should not be specified together
  • onSuccess: called when the request finishes successfully. This function will receive two parameters:
    • new_token: the new token obtained that you can use to access the ObjectStorage
    • data: the catalogue of available services for the tenant
  • onFailure: called when the request finish with errors

Presenter Notes

Getting the authentication token

The next snippet shows you how to use this function. In this case we will use the tenant id obtained in the previous code. Note that we will also process the data parameter in order to get the ObjectStorage URL:

keystone.getAuthToken({
    tenantId: data.tenants[0].id,
    onSuccess: function (new_token, data) {
        for (i = 0; i < data.access.serviceCatalog.length; i++) {
            if (data.access.serviceCatalog[i].type === 'object-store') {
                object_storage = data.access.serviceCatalog[i].endpoints[0].publicURL;
            }
        }
    },
    onFailure: function () {
        document.getElementById('api_token').textContent = 'Fail';
    }
});

Presenter Notes

Using Object Storage

Connecting with the ObjectStorage Server

Presenter Notes

Connecting with the ObjectStorage Server

Once that you have the URL of the ObjectStorage server, we can connect to it. To do so, we must use the following function:

objectStorage = ObjectStorageAPI(url)

In our case we have saved the ObjectStorage Server URL in the object_storage variable, so our code should be the following one:

objectStorage = ObjectStorageAPI(object_storage)

Presenter Notes

Using Object Storage

Listing the content available in a container

Presenter Notes

Listing the content available in a container

When we are connected to a ObjectStorage Server, we are able to list all the content available in a container. To do so, we should use the listContainer function:

objectStorage.listContainer(container[, options])

The container argument is the name of the container while the options argument should contain the following fields:

  • token: The token obtained previously in the getAuthToken function
  • onSuccess: called when the request finishes successfully. This function receives as argument the list of available files in the container
  • onFailure: called when the request finish with errors

Presenter Notes

Listing the content available in a container

In the next example, we will show we will get the available files in the integrationTests container, and we will show the name of the first one.

objectStorage.listContainer('integrationTests', {
    token: token,

    onSuccess: function(file_list) {
        document.getElementById('file_name').textContent = file_list[0].name;
    },

    onFailure: function () {
        document.getElementById('file_count').textContent = 'Fail';
    }
});

Presenter Notes

Using Object Storage

Uploading a file

Presenter Notes

Uploading a file

If you are connected to the ObjectStorage, you can also upload a file easily. To do so, you must use the uploadFile function:

objectStorage.uploadFile(container, file[, options])

container is the name where the file is going to be uploaded, while file is the content to be uploaded. The options argument should contain the following fields:

  • token: The token obtained previously in the getAuthToken function
  • file_name: The name used to save the uploaded content in the container
  • onSuccess: called when the request finishes successfully. This function does not receive any arguments
  • onFailure: called when the request finish with errors

Presenter Notes

Uploading a file

Here you can see how to upload a text file containing "Hello world!".

var blob = new Blob(["Hello world!"], { type: "text/plain" });
objectStorage.uploadFile('integrationTests', blob, {
    token: token,
    file_name: 'test1.txt',
    onSuccess: function() {
        document.getElementById('file_upload').textContent = 'OK';
    },
    onFailure: function () {
        document.getElementById('file_upload').textContent = 'Fail';
    }
});

Presenter Notes

Using Object Storage

Deleting a file

Presenter Notes

Deleting a file

It's useful to upload a file, but in some occasions you will want to delete it. To do so, you have to use the deleteFile function:

objectStorage.deleteFile(container, file_name[, options])

container is the name of the container where the file is going to be deleted while file_name is the name of the file to delete. The options argument should contain the following fields:

  • token: The token obtained previously in the getAuthToken function
  • onSuccess: called when the request finishes successfully. This function does not receive any arguments
  • onFailure: called when the request finish with errors

Presenter Notes

Deleting a file

The following example shows how to delete the file that we have created in the previous step:

objectStorage.deleteFile('integrationTests', file_name, {
    token: token,
    onSuccess: function() {
        document.getElementById('file_deletion').textContent = 'OK';
    },
    onFailure: function () {
        document.getElementById('file_deletion').textContent = 'Fail';
    }
});

Presenter Notes

Using Object Storage

Test it yourself!

Presenter Notes

Test it yourself!

We think that the best way to learn to use this feature is using it. For this reason we offer you a very simple example based on this guide. Check the code and modify as you like and test if it works. This widget will only work if you create a instanceTests container before running it, otherwise it will fail.

Presenter Notes

Thanks!

Presenter Notes