Using sstableloader

sstableloader tool can be used to load data in to Cassandra cluster in batch wise. First we need to generate sstable by reading the external data resource (in this example below from .csv file) and sstableloader stream sstable data files to Cassandra cluster confirming the replication stragegy of the cluster . Following is as example code for loading data from .csv files to Cassandra.


  1. Download and install Cassandra from here and use Cassandra GUI to monitor your cluster. 
  2. Lets consider a .csv file with fields uuid, firstname, lastname, password, age, email
5bd8c586-ae44-11e0-97b8-0026b0ea8cd0, Alice, Smith, asmi1975, 32, alice.smith@mail.com

4bd8cb58-ae44-12e0-a2b8-0026b0ed9cd1, Bob, Miller, af3!df8, 28, bob.miller@mail.com

1ce7cb58-ae44-12e0-a2b8-0026b0ad21ab, Carol, White, cw1845?, 49, c.white@mail.com

Lets consider creating one column family  'Users' with this csv. So create the keyspace 'Demo'  and column family 'Users'.
create keyspace Demo;

use Demo;

create column family Users

    with key_validation_class=LexicalUUIDType

    and comparator=AsciiType

    and column_metadata=[

        { column_name: 'firstname', validation_class: AsciiType }

        { column_name: 'lastname', validation_class: AsciiType }

        { column_name: 'password', validation_class: AsciiType }

        { column_name: 'age', validation_class: LongType, index_type: KEYS }

        { column_name: 'email', validation_class: AsciiType }];



     3.  Create sstable using SSTableSimpleUnsortedWriter class

configuration - To compile this file the Cassandra jar (>= 0.8.2) needs to be in the classpath (javac -cp <path_to>/apache-cassandra-1.1.1.jar DataImportExample.java). To run it, the Cassandra jar needs to be present as well as the jar of the librairies used by Cassandra (those in the lib/ directory of Cassandra source tree). Validcassandra.yaml and log4j configuration files should also be accessible; typically, this means the conf/directory of the Cassandra source tree should be in the classpath.

  • If you are using Eclipse IDE add the Cassandra/conf folder path to classpath-->Advanced settings-->Add External Folder--> then add apache-cassandra-x.x.x/conf folder in to path.
  • In Intellij Idea , got to Run-->Edit Configurations-->Application-->Configuration-->VM Options. There you should give the path to cassandra.yaml as follows.
  • Dcassandra-foreground -Dcassandra.config=file:///<path to/apache-cassandra-1.1.2/conf/cassandra.yaml> -ea -Xmx1G
 
import java.nio.ByteBuffer;
import java.io.*;
import java.util.UUID;
 
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.io.sstable.SSTableSimpleUnsortedWriter;
import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
import static org.apache.cassandra.utils.UUIDGen.decompose;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.RandomPartitioner;
 
public class DataImportExample
{
    static String filename;
 
    public static void main(String[] args) throws IOException
    {
        filename = "/home/amila/FYP/cdr_001.csv";
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String keyspace = "Demo";
        File directory = new File(keyspace);
        if (!directory.exists()){
          directory.mkdir();}
 
        // random partitioner is created, u can give the partitioner as u want
        IPartitioner partitioner = new RandomPartitioner();
 
        SSTableSimpleUnsortedWriter usersWriter = new SSTableSimpleUnsortedWriter(
                directory,partitioner,keyspace,"Users",AsciiType.instance,null,64);
    
        String line;
        int lineNumber = 1;
        CsvEntry entry = new CsvEntry();
        // There is no reason not to use the same timestamp for every column in that example.
        long timestamp = System.currentTimeMillis() * 1000;
 
        while ((line = reader.readLine()) != null)
        {
          if (entry.parse(line, lineNumber))
          {
            ByteBuffer uuid = ByteBuffer.wrap(decompose(entry.key));
            usersWriter.newRow(uuid);
            usersWriter.addColumn(bytes("firstname"), bytes(entry.firstname), timestamp);
            usersWriter.addColumn(bytes("lastname"), bytes(entry.lastname), timestamp);
            usersWriter.addColumn(bytes("password"), bytes(entry.password), timestamp);
            usersWriter.addColumn(bytes("age"), bytes(entry.age), timestamp);
            usersWriter.addColumn(bytes("email"), bytes(entry.email), timestamp);
            }
            lineNumber++;
        }
        // Don't forget to close!
        usersWriter.close();
        
        System.exit(0);
    }
 
    static class CsvEntry
    {
        UUID key;
        String firstname;
        String lastname;
        String password;
        long age;
        String email;
 
        boolean parse(String line, int lineNumber)
        {
            // Ghetto csv parsing
            String[] columns = line.split(",");
            if (columns.length != 6)
            {
                System.out.println(String.format("Invalid input '%s' at line %d of %s", line, lineNumber, filename));
                return false;
            }
            try
            {                                                                                                  
                key = UUID.fromString(columns[0].trim());
                firstname = columns[1].trim();
                lastname = columns[2].trim();
                password = columns[3].trim();
                age = Long.parseLong(columns[4].trim());
                email = columns[5].trim();
                return true;
            }
            catch (NumberFormatException e)
            {
                System.out.println(String.format("Invalid number in input '%s' at line %d of %s", line, lineNumber, filename));
                return false;
            }
        }
    }
}
 
After you run this you will see a folder called Demo is created and there you can find sstables created with .db and .sh1 files.
for an example in the above case it will create sstables as below (when keySpace="Demo" and Column family = "Users")

Demo-Users-hd-1-Data.db
Demo-Users-hd-1-Digest.sha1
Demo-Users-hd-1-Filter.db
Demo-Users-hd-1.index.db
Demo-Users-hd-1.Statistics.db

     4.  Loading sstables to Cassendra using sstableLoader.

Loading sstables from command  

  • Go to CASSANDRA_HOME/bin  then , run this command ,  ./sstableloader Demo  or
  • Go to CASSANDRA_HOME and run command, bin/sstableloader/some/path/to/the<KeyspaceName>
  • If you are running the all from localhost try the following steps,
       -   Set another loop-back address with command(linix)  :  sudo ifconfig lo:0 127.0.0.2 netmask 255.0.0.0 up
      -   Get a copy of the running Cassandra folder and do the following configuratons.
         Set the rpc address and listen address in  /conf/casandra.yaml to 127.0.0.2. if you want to listen all   interfaces you can set rpc address to 0.0.0.0 
      -   run sstableloader from the copied Cassandra with using command
         ./sstableloader -d 127.0.0.2 <path to sstable../keyspace_name/columnfamily_name>
        Relevant to above example the path should be given as ./sstableloader -d 127.0.0.2 pathtosstables/Demo/Users

To run sstableloader from java module 

If you want to run sstableLoader through your java module you can run following class. " org.apache.cassandra.tools.BulkLoader.main(args) ".Where "args" will be array of values you supply during the run of sstableloader from command line.

Load sstables using  JMX client

with my personal experience using JMX client is much faster than using sstableloader

 
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
 
import org.apache.cassandra.service.StorageServiceMBean;
 
public class JmxBulkLoader {
 
    private JMXConnector connector;
    private StorageServiceMBean storageBean;
 
    public JmxBulkLoader(String host, int port) throws Exception
    {
        connect(host, port);
    }
 
    private void connect(String host, int port) throws IOException, MalformedObjectNameException
    {
        JMXServiceURL jmxUrl = new JMXServiceURL(String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi", host, port));
        Map env = new HashMap();
        connector = JMXConnectorFactory.connect(jmxUrl, env);
        MBeanServerConnection mbeanServerConn = connector.getMBeanServerConnection();
        ObjectName name = new ObjectName("org.apache.cassandra.db:type=StorageService");
        storageBean = JMX.newMBeanProxy(mbeanServerConn, name, StorageServiceMBean.class);
    }
 
    public void close() throws IOException
    {
        connector.close();
    }
    
    public void bulkLoad(String path) {
        storageBean.bulkLoad(path);
    }
    
    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            throw new IllegalArgumentException("usage: paths to bulk files");
        }
        JmxBulkLoader np = new JmxBulkLoader("localhost", 9160);
        for (String arg : args) {
            np.bulkLoad(arg);
        }
        np.close();
    }
}}

35

View comments

  1. Hi Amila,

    Great blog! Is there an email address I can contact you in private?

    ReplyDelete
  2. Hi Amila. Thanks for the blog. I noticed there is some errors with this code though. They seem to be fixed here


    https://gist.github.com/3774733

    ReplyDelete
  3. i m facing problem in sstableloader. when i run the sstableloader command it gives me message like "Could not retrieve endpoint ranges: "

    ReplyDelete
    Replies
    1. make sure you give the path to the sstables correctly, the path should end as "path to sstables../keyspace_name/columnfamily_name"

      Delete
    2. Hi,

      After running the above code in eclipse sstables are generated in my working Directory and i got another instance of cassandra with listen address as 127.0.0.2 and rpc as 127.0.0.2 and ran the command ./sstableloader -d 127.0.0.2 /home/Desktop/workspace/Demo/Users(path to generated ss tables).but im getting the error:"Could not retrieve endpoint ranges".

      Delete
    3. Hi, please try following steps-

      1. Run nodetool status command to check how many nodes you have in your cluster.

      2. Now give IP of all the nodes found in above command separated by comma. Make sure, if there is any node with status DN/DL, you use -i in sstableloader command to ignore the node which is dead.

      Delete
  4. Thanks for the nice informative blog :)

    ReplyDelete
  5. When compiling the code with cassandra 1.1.6, the following import was needed
    import org.apache.cassandra.dht.*;

    ReplyDelete
    Replies
    1. Thank you anon. This post was written with Cassandra 1.1.1 version, so there can be differences when using Cassandra newer versions.

      Delete
  6. While trying with JMX Client, where I have given the arg as 'C:\Anand\Workspace\H2C_POC\Customer' in Run configurations of my eclipse, I get the following error. Please let me know if i am missing something here.

    Exception in thread "main" java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
    java.io.EOFException]
    at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:338)
    at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
    at com.homedepot.sstables.JmxBulkLoader.connect(JmxBulkLoader.java:35)
    at com.homedepot.sstables.JmxBulkLoader.(JmxBulkLoader.java:27)
    at com.homedepot.sstables.JmxBulkLoader.main(JmxBulkLoader.java:55)
    Caused by: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
    java.io.EOFException]
    at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:101)
    at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:185)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1886)
    at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1856)
    at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:257)
    ... 4 more
    Caused by: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
    java.io.EOFException
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:97)
    ... 9 more
    Caused by: java.io.EOFException
    at java.io.DataInputStream.readByte(DataInputStream.java:250)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:228)
    ... 13 more

    ReplyDelete
    Replies
    1. Did you follow the steps under 'To load sstables from command line' ..If you are running the all from localhost try the following steps, ?? and make sure that 'Customer' is your columnfamily name

      Delete
    2. Name of my keyspace is Customers. Column family name is Users (same as above).
      I am working on windows environment. The command line options seems to be for Linux. So, I tried the next 2 options suggested above:

      1) sstableloader using java module - Created a java class which invokes org.apache.cassandra.tools.BulkLoader.main with the following args:
      -d '127.0.0.1' 'C:\Anand\Workspace\H2C_POC\Customer'
      I end up having "Unknown directory: 'C:\Anand\Workspace\H2C_POC\Customer'" error.
      Is there a problem with my directory structure? Is it expecting a Linux directory structure over there?
      Even appended the column family name at the end. And stil got Unknown directory error.

      2) In JMX client also, if I appened the columnfamily name 'Users' to my arguement, I end up having the javax.naming.CommunicationException.
      Am I supposed to change any values in connect() method?

      Delete
    3. In both cases you have to include the columnfamily name at the end , as an eg: 'C:\Anand\Workspace\H2C_POC\Customer\Users(in your case). In JMX client you don't need to change anything just have to give the path to your sstables crated as above and give local host IP and port in line JmxBulkLoader np = new JmxBulkLoader("localhost", 9160);.

      Delete
  7. While using the JMXInterface use the port number 7199 instead of 9160. For more details read this http://wiki.apache.org/cassandra/JmxInterface.

    ReplyDelete
  8. Thanks Amila for the details. I followed the steps and while running the bulkloader from Java, I get this exception

    Exception in thread "main" java.lang.AssertionError
    at org.apache.cassandra.io.sstable.SSTableReader.open(SSTableReader.java:148)
    at org.apache.cassandra.io.sstable.SSTableReader.open(SSTableReader.java:143)
    at org.apache.cassandra.io.sstable.SSTableLoader$1.accept(SSTableLoader.java:98)
    at java.io.File.list(File.java:1010)
    at org.apache.cassandra.io.sstable.SSTableLoader.openSSTables(SSTableLoader.java:69)

    ReplyDelete
    Replies
    1. Create a folder named with your column family inside the folder(keyspace) that was created by "DataImportExample" class. then try to load.

      Delete
  9. Thanks Nayan for your response. Yes, I created another folder, still it gives the same error. I am using Cassandra 1.1.1 jars. Any other thoughts ?
    Thanks !

    ReplyDelete
    Replies
    1. Sorry i missed one line. Please move all the files those created using "DataImportExample" inside the newly created folder(column family). hope this will allow you to load data.

      Delete
    2. Hello everyone,

      Has anyone faced or solved this issue with JMX client code. I am creating sstables successgully placing them under correct directory structure and passing it as an arg to JMXclient code. I get the following error :-

      Caused by: java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:
      java.io.EOFException
      at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:209)
      at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
      at com.sun.jmx.remote.internal.PRef.invoke(Unknown Source)
      at javax.management.remote.rmi.RMIConnectionImpl_Stub.invoke(Unknown Source)
      at javax.management.remote.rmi.RMIConnector$RemoteMBeanServerConnection.invoke(RMIConnector.java:993)
      at javax.management.MBeanServerInvocationHandler.invoke(MBeanServerInvocationHandler.java:288)
      ... 9 more
      Caused by: java.io.EOFException
      at java.io.DataInputStream.readByte(DataInputStream.java:250)
      at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:195)
      ... 14 more

      Delete
  10. I am using Cassandra 1.2 for Bulk Load..

    This is the message I get after I run sstableloader.

    ./sstableloader -d 127.0.0.2 --debug /home/ubuntu/VIQ-Cloud/software/apache-cassandra-1.2.5/data/vng_sugar_cookie_prod/ja_job_master
    Streaming revelant part of /home/ubuntu/VIQ-Cloud/software/apache-cassandra-1.2.5/data/vng_sugar_cookie_prod/ja_job_master/vng_sugar_cookie_prod-ja_job_master-ic-1-Data.db to [/127.0.0.1]

    progress: [/127.0.0.1 1/1 (100)] [total: 100 - 0MB/s (avg: 0MB/s)]


    But, when I do a select * from cqlsh I get the following error:
    "Request did not complete within rpc_timeout."

    from cassandra.yaml
    rpc_address: 0.0.0.0
    Iam stuck for 2 days at this point..
    Please advise.
    Thanks in advance

    ReplyDelete
  11. HI,

    Thanx for the informative post.

    While running DataImportExample.java I am getting an exception

    i.e.

    null; Can't construct a java object for tag:yaml.org,2002:org.apache.cassandra.config.Config; exception=Cannot create property=hinted_handoff_throttle_in_kb for JavaBean=org.apache.cassandra.config.Config@272c6f83; Unable to find property 'hinted_handoff_throttle_in_kb' on class: org.apache.cassandra.config.Config
    Invalid yaml; unable to start server.

    ReplyDelete
  12. Hi Amila,

    Thank you for your post. I am trying to load data from CSV to cassandra table. Howevere, SSTableSimpleUnsortedWriter is not getting recognised for me in eclipse. I have added dependencies in Maven and I guess I have all the required jars, I added apache-cassandra/conf in libraries in build path....but it is still not working. Could you please help me? Any idea what could be reason? I am using datastax community edition of cassandra....

    Thank you,
    Vamshi

    ReplyDelete
  13. Can you confirm that apache-cassandra-x.x.x.jar is present in your .m2 maven repository(since you have added apache cassandra as a maven dependency ) and please check whether you can find SSTableSimpleUnsortedWriter class inside that jar. Hope you have refreshed maven dependencies on your eclipse project.

    ReplyDelete
  14. Hi Amiila,

    I added jar and now I am able to import SSTableSimpleUnsortedWriter class. But when I run this program, I am getting errors. Let me explain you my problem clearly.

    Problem:

    1. I have installed cassandra in same machine and I understand that I need to makechanges in cassandra,yaml file. I read somewhere that we need to create loopback ip address and duplicate cassandra folder and make changes which I am confused about. Could you please help me in solving this?

    2. I tried using JMX but I want to know if JMX is used to generate SSTables or is it used after SSTables are generated to copy into cassandra? Could you please let me know what that URL given in jmxurl mean?

    I am a beginner in cassandra, so my question might sound silly. Right now, my priority would be point1. Please help me.

    Thank you,
    Vamshi

    ReplyDelete
    Replies
    1. setting loopback address(1) and using JMX client are for loading the sstables you created to cassandra. Before all could you create sstables (files similar to Demo-Users-hd-1-Data.db) using DataImportExample class?

      Delete
    2. Hi Amila,

      I could successfully generate SSTables. Could you please help me in moving forward from here on a local cassandra machine.? I am using Windows OS. Is linux required or can we do it on Windows?

      Thank you,
      Vamshi

      Delete
    3. Hi Vamshi,
      So now you have set up your windows machine to run Cassandra right ?. You can simply use JMX client java code given in this post to load your sstables to Cassandra. Give your cassanda running host, port and path to your created SSTables in relevant places in the code.

      Delete
    4. Hi Amila,

      Thank you for the information. I tried JMX and the only problem that I am facing is that it is not correcly picking up folder location.

      I have my keyspace folder named 'Demo' and its location is 'C:\Users\vamshi_krishna\Desktop\Demo'. But when I give this location as an argument or as argument like below:

      JmxBulkLoader np = new JmxBulkLoader("localhost", 7199);
      np.bulkLoad("C:\\Users\\vamshi_krishna\\Desktop\\Demo");

      It is giving me the following error:

      Exception in thread "main" java.lang.AssertionError: Unknown keyspace Desktop
      at org.apache.cassandra.db.Keyspace.(Keyspace.java:262)
      at org.apache.cassandra.db.Keyspace.open(Keyspace.java:110)
      at org.apache.cassandra.db.Keyspace.open(Keyspace.java:88)
      at org.apache.cassandra.service.StorageService.constructRangeToEndpointMap(StorageService.java:1187)
      at org.apache.cassandra.service.StorageService.getRangeToAddressMap(StorageService.java:1072)
      at org.apache.cassandra.service.StorageService$6.init(StorageService.java:3498)
      at org.apache.cassandra.io.sstable.SSTableLoader.stream(SSTableLoader.java:149)


      Could you please let me know if I have to do any thing else? I think I will be able to do bulk load if this issue is resolved. Please help me.

      Thank you,
      Vamshi



      Delete
    5. make sure you give the path to the sstables correctly, the path should end as "path to sstables../keyspace_name/columnfamily_name". Your sstables should be inside a folder which the name of the folder is similar to ColumnFamily name(not key space name). Create a folder named with your column family inside the folder(keyspace) that was created by "DataImportExample" class. then try to load.

      Delete
  15. Thanks Amila for the post.Was really helpful.
    Though I had some hiccups.My csv file has 400 columns.Everything works great for small files few MBs.
    For several GBs it throws a error as :

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at sun.nio.cs.UTF_8.newEncoder(UTF_8.java:72)
    at java.lang.StringCoding.encode(StringCoding.java:348)
    at java.lang.String.getBytes(String.java:939)
    at org.apache.cassandra.utils.ByteBufferUtil.bytes(ByteBufferUtil.java:231)
    at sstablegenerator.Sstablegenerator.main(Sstablegenerator.java:385)

    Any clues.Thanks

    ReplyDelete
    Replies
    1. You're out of memory. Increase the amount of memory to give to the JVM.

      ref to error - http://www.coderanch.com/t/329142/java/java/Exception-thread-main-java-lang

      Delete
  16. Hi Amila,
    Firstly, thanks for your post, i followed the above steps but i got his error. could you tell me how to solve this?

    Missing sstable directory argument
    usage: sstableloader [options]
    --
    Bulk load the sstables found in the directory to the configured
    cluster.The parent directory of is used as the keyspace name.
    So for instance, to load an sstable named Standard1-g-1-Data.db into
    keyspace Keyspace1, you will need to have the files Standard1-g-1-Data.db
    and Standard1-g-1-Index.db in a directory Keyspace1/Standard1/ in the
    directory and call: sstableloader Keyspace1/Standard1
    --
    Options are:
    -alg,--ssl-alg SSL: algorithm
    (default: SunX509)
    -ciphers,--ssl-ciphers SSL: comma-separated
    list of encryption
    suites to use
    -d,--nodes try to connect to
    these hosts (comma
    separated) initially
    for ring information
    --debug display stack traces
    -h,--help display this help
    message
    -i,--ignore don't stream to this
    (comma separated)
    list of nodes
    -ks,--keystore SSL: full path to
    keystore
    -kspw,--keystore-password SSL: password of the
    keystore
    --no-progress don't display
    progress
    -p,--port port used for rpc
    (default 9160)
    -prtcl,--ssl-protocol SSL: connections
    protocol to use
    (default: TLS)
    -pw,--password password for
    cassandra
    authentication
    -st,--store-type SSL: type of store
    -t,--throttle throttle speed in
    Mbits (default
    unlimited)
    -tf,--transport-factory Fully-qualified
    ITransportFactory
    class name for
    creating a connection
    to cassandra
    -ts,--truststore SSL: full path to
    truststore
    -tspw,--truststore-password SSL: password of the
    truststore
    -u,--username username for
    cassandra
    authentication
    -v,--verbose verbose output

    ReplyDelete
  17. Thanks for the post..
    How fast is this tool?
    I have 160GB csv file to insert.
    Does it work with big files? How much time should I expect?

    ReplyDelete
  18. We are trying to upload a simple csv file (with 3 lines of data) into the cassandra using the SSTABLELOADER . The steps are followed as mentioned in your blog

    We are getting the following streaming exception when we executed the sstableloader.

    Note: we are using the : datastax community AMI from EC2

    Please let us know for any information to resolve this problem.

    ubuntu@:~/new$ ~/sstableloader -d 127.0.0.2 demo/users
    Established connection to initial hosts
    Opening sstables and calculating sections to stream
    Streaming relevant part of demo/users/demo-users-ka-1-Data.db to [/172.31.19.233, /172.31.19.234, /172.31.19.235]
    progress: [/172.31.19.233]0:1/1 403% [/172.31.19.234]0:1/1 200% [/172.31.19.235]0:1/1 348% total: 300% 0 MB/s(avg: 0 MB/s)WARN 09:13:58 [Stream #ed27f630-55dd-11e4-89e1-c5cbeff8b318] Stream failed
    Streaming to the following hosts failed:
    [/172.31.19.233, /172.31.19.234, /172.31.19.235]
    java.util.concurrent.ExecutionException: org.apache.cassandra.streaming.StreamException: Stream failed
    at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299)
    at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286)
    at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116)
    at org.apache.cassandra.tools.BulkLoader.main(BulkLoader.java:112)
    WARN 09:13:58 [Stream #ed27f630-55dd-11e4-89e1-c5cbeff8b318] Stream failed
    Caused by: org.apache.cassandra.streaming.StreamException: Stream failed
    at org.apache.cassandra.streaming.management.StreamEventJMXNotifier.onFailure(StreamEventJMXNotifier.java:85)
    at com.google.common.util.concurrent.Futures$4.run(Futures.java:1172)
    at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297)WARN 09:13:58 [Stream #ed27f630-55dd-11e4-89e1-c5cbeff8b318] Stream failed

    at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156)
    at com.google.common.util.concurrent.ExecutionList.execute(ExecutionList.java:145)
    at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:202)
    at org.apache.cassandra.streaming.StreamResultFuture.maybeComplete(StreamResultFuture.java:208)
    at org.apache.cassandra.streaming.StreamResultFuture.handleSessionComplete(StreamResultFuture.java:184)
    at org.apache.cassandra.streaming.StreamSession.closeSession(StreamSession.java:357)
    at org.apache.cassandra.streaming.StreamSession.sessionFailed(StreamSession.java:562)
    at org.apache.cassandra.streaming.StreamSession.messageReceived(StreamSession.java:417)
    at org.apache.cassandra.streaming.ConnectionHandler$IncomingMessageHandler.run(ConnectionHandler.java:295)
    at java.lang.Thread.run(Thread.java:744)

    ReplyDelete

Securing the API access with JWT based Authentication

Management server REST API requests can be secured with JWT authentication. By default authentication is disabled and you can enable it by changing the ''console.auth.jwt.on" property to "true" in management.properties file.   
 
Following diagram shows the main authentication flow of application.


1. Receive username, password from web interface on user login
2. Authenticate the user from shiro realm (Supported file based user store realm)
3. Successful authentication by the ldap server
4. Create a JWT token including the following claims
    - username, user_permissions, user_ldap_groups, issuer (configurable), expiration_date (configurable)
5. Signs this JWS token with the specified Message Authentication Code (MAC) signer using a shared key
6. Encrypt the token with Base64 with a hashkey
7. Save the encrypted token over username in in-memory cache(This is to avoid disk access on later for token validation)
8. Return the encrypted token to the user
After user get a valid token at the first login, he can use the same token in next logins until the token expires. Following diagram shows the authentication flow when user request come with a JWT token.

 


 

1. Request is filtered by JWTAuthorizationFilter.
2. JWT token extracted from AUTHORIZATION header
3. Verify the token whether the token is expired and similar to the token issued by the application earlier. (first compares with token saved in the cache)
4. Decrypt the token
5. Token values are fed to AuthDataContainer object (these information is used over the application for authorization purpose and this is valid only for a one session)
6. Authentication success returned to the user

Following table explains how the token request and a sample api call (get request) is done.

Authentication
Request
Response
Token request
POST /management/auth HTTP/1.0
Connection: close
Content-Length: 42
Content-Type: application/json; charset=UTF-8
Host: localhost:8011
User-Agent: <>




{"username":"admin","password":"password"}
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=1qj32rt2mppjfjhnah8zre3st;Path=/
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 29-Nov-2016 06:55:02 GMT
Content-Type: application/json
Content-Length: 982
Server: Jetty(9.2.3.v20140905)

 {"msg":"bDd6RllXSX……..."}
API call (GET)
GET /management/project HTTP/1.0
Connection: close
Authorization: bDd6RllXSX……...
Host: localhost:8011
User-Agent: <>


HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=17n23j1souoiraqsompt9jah5;Path=/
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Tue, 29-Nov-2016 09:16:21 GMT
Content-Type: application/json
Content-Length: 164
Server: Jetty(9.2.3.v20140905)

<response body...>

Security related properties in management.properties file


Property
Description
console.auth.jwt.on
‘True’ or ‘false’ to enable or disable api security
jwt.lifetime
JWT token lifetime in milliseconds
console.auth.url
Authentication request URL
console.auth.unauthorized
Path to direct for unauthorized requests
shiro.users
Users and password file location. Each user need to be added in a new line with the format <user><SPACE><password>
shiro.permissions
Users and permission file location. Each user permission need be added in a new line with the format ‘<username><SPACE><comma separated permissions>’
jwt.encryption.key
JWT token encryption key
jwt.shared.key
JWT shared key

1

View comments

Blog Archive
looking for??
About me
About me
Total Pageviews
Total Pageviews
222949
Popular Posts
Popular Posts
Loading
Dynamic Views theme. Theme images by mattjeacock. Powered by Blogger.