Feature/resource descriptor clone

Hi,

While testing against an Olive (Junos virtual machine) I ran into a number of issues with cloning of ResourceDescriptor and persistence.

To reproduce, start with a fresh Mantychore instance and create a resource:

    behrmann@behrmann-x220:/tmp/manticore$ KARAF_DEBUG=1 sh ./platform/target/mantychore/opennaas-1.0.0-SNAPSHOT/bin/mantychore.sh
    mantychore.sh: Enabling Java debug options: -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
    Listening for transport dt_socket at address: 5005
    mmmm                                  mmm   mm                        mmmm
    ##""##                                 ###   ##                      m#""""#
    ##    ##  ##m###m    m####m   ##m####m  ##"#  ##   m#####m   m#####m  ##m
    ##    ##  ##"  "##  ##mmmm##  ##"   ##  ## ## ##   " mmm##   " mmm##   "####m
    ##    ##  ##    ##  ##""""""  ##    ##  ##  #m##  m##"""##  m##"""##       "##
    ##mm##   ###mm##"  "##mmmm#  ##    ##  ##   ###  ##mmm###  ##mmm###  #mmmmm#"
    """"    ## """      """""   ""    ""  ""   """   """" ""   """" ""   """""
    ##
    Karaf Shell (OpenNaaS's)

    Hit '<tab>' for a list of available commands
    and '[cmd] --help' for help on a specific command.
    Hit '<ctrl-d>' or 'osgi:shutdown' to shutdown Karaf.

    OpenNaaS>resource:create /tmp/olive1.descriptor
    [INFO] Descriptor loaded for resource router:olive1
    [INFO] Created resource router:olive1
    [INFO] Created 1 resource/s of 1
    OpenNaaS>resource:list 
    [INFO] Found 1 resources.
    [INFO]      TYPE: router     ID: olive1     STATE: INITIALIZED
    OpenNaaS>^D

Quit and restart to ensure that the resource is loaded back from persistent storage:

    behrmann@behrmann-x220:/tmp/manticore$ KARAF_DEBUG=1 sh ./platform/target/mantychore/opennaas-1.0.0-SNAPSHOT/bin/mantychore.sh
    mantychore.sh: Enabling Java debug options: -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
    Listening for transport dt_socket at address: 5005
    mmmm                                  mmm   mm                        mmmm
    ##""##                                 ###   ##                      m#""""#
    ##    ##  ##m###m    m####m   ##m####m  ##"#  ##   m#####m   m#####m  ##m
    ##    ##  ##"  "##  ##mmmm##  ##"   ##  ## ## ##   " mmm##   " mmm##   "####m
    ##    ##  ##    ##  ##""""""  ##    ##  ##  #m##  m##"""##  m##"""##       "##
    ##mm##   ###mm##"  "##mmmm#  ##    ##  ##   ###  ##mmm###  ##mmm###  #mmmmm#"
    """"    ## """      """""   ""    ""  ""   """   """" ""   """" ""   """""
    ##
    Karaf Shell (OpenNaaS's)

    Hit '<tab>' for a list of available commands
    and '[cmd] --help' for help on a specific command.
    Hit '<ctrl-d>' or 'osgi:shutdown' to shutdown Karaf.

    OpenNaaS>resource:list
    [INFO] Found 1 resources.
    [INFO]      TYPE: router     ID: olive1     STATE: INITIALIZED

Now create a logical router to force Mantychore to clone the resource:

    OpenNaaS>protocols:context router:olive1 netconf ssh://behrmann:xxx@192.168.56.2:1234/netconf
    [INFO] Context registered for resource router:olive1
    OpenNaaS>resource:start router:olive1 
    [INFO] Resource router:olive1 started.
    [INFO] Started 1 resource/s of 1
    OpenNaaS>chassis:createlogicalrouter router:olive1 test
    OpenNaaS>queue:execute router:olive1 
    Executing queue... 
    [ERROR] Error executing queue.
    [ERROR] org.opennaas.core.resources.capability.CapabilityException: org.opennaas.core.resources.ResourceException: org.hibernate.collection.PersistentMap cannot be cast to java.util.HashMap
    -1
    OpenNaaS>


The failure is caused by the ResourceDescriptor.clone method casting a map to HashMap. The map is however a PersistentMap generated by Hibernate, so the cast fails. The solution is to copy the map into a new HashMap rather than relying on cloning unknown objects.


Once that problem was fixed I ran into another problem. The cloned CapabilityDescriptor and CapabilityProperties objects contained the original identifier. Thus Hibernate failed to persist them due to key constraints of the database. The solution to that problem is to not copy the ID fields when cloning those objects (I am no Hibernate expert [I'm more familiar with DataNucleus and JDO], but Google suggests that this is the right solution). I tried to find other uses of clone() and found none. Neither class implements the Clonable interface, so I think it is safe to assume that clone() is only used for this particular purpose.


I wrote unit tests for both problems. While running the unit tests I ran into a third bug triggering a NullPointerException when cloning. This happens when the capabilityInformation field isn't set (as is the case in the test fixture used by the unit tests).

The branch contains fixes for the above mentioned issues. Detailed information can be found in each commit log. Please review and pull.

Cheers,

/gerd