diff options
50 files changed, 4128 insertions, 1897 deletions
diff --git a/distribution/README.md b/distribution/README.md new file mode 100644 index 00000000..cced66dc --- /dev/null +++ b/distribution/README.md @@ -0,0 +1,12 @@ +# Docker Setup +--------------- + +```bash +# Start the Container +docker run -d --name cassandra_music -v $PWD/data:/var/lib/cassandra cassandra_music:3.0 +# Load cql script into DB +docker run -it --link cassandra1:cassandra -v $PWD/music.cql:/music.cql cassandra_music1:3.0 cqlsh -u cassandra -p cassandra cassandra1 -f music.cql +# Start cqlsh +docker run -it --link cassandra_music:cassandra cassandra_music:3.0 cqlsh -u cassandra -p cassandra cassandra1 + +``` diff --git a/distribution/cassandra/Dockerfile b/distribution/cassandra/Dockerfile new file mode 100644 index 00000000..9405fcb3 --- /dev/null +++ b/distribution/cassandra/Dockerfile @@ -0,0 +1,9 @@ +#registry.hub.docker.com/ +FROM library/cassandra:3.0 +RUN mkdir -p /docker-entrypoint-initdb.d && mkdir -p /home/cassandra/.cassandra && chown -R cassandra /home/cassandra +COPY cassandra.yaml /etc/cassandra/ +COPY music_single.cql /docker-entrypoint-initdb.d/ +COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod 755 /usr/local/bin/docker-entrypoint.sh && chown -R cassandra /docker-entrypoint-initdb.d + +ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/distribution/cassandra/cassandra.yaml b/distribution/cassandra/cassandra.yaml new file mode 100644 index 00000000..d4af64af --- /dev/null +++ b/distribution/cassandra/cassandra.yaml @@ -0,0 +1,1001 @@ +# Cassandra storage config YAML + +# NOTE: +# See http://wiki.apache.org/cassandra/StorageConfiguration for +# full explanations of configuration directives +# /NOTE + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'Test Cluster' + +# This defines the number of tokens randomly assigned to this node on the ring +# The more tokens, relative to other nodes, the larger the proportion of data +# that this node will store. You probably want all nodes to have the same number +# of tokens assuming they have equal hardware capability. +# +# If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility, +# and will use the initial_token as described below. +# +# Specifying initial_token will override this setting on the node's initial start, +# on subsequent starts, this setting will apply even if initial token is set. +# +# If you already have a cluster with 1 token per node, and wish to migrate to +# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations +num_tokens: 256 + +# Triggers automatic allocation of num_tokens tokens for this node. The allocation +# algorithm attempts to choose tokens in a way that optimizes replicated load over +# the nodes in the datacenter for the replication strategy used by the specified +# keyspace. +# +# The load assigned to each node will be close to proportional to its number of +# vnodes. +# +# Only supported with the Murmur3Partitioner. +# allocate_tokens_for_keyspace: KEYSPACE + +# initial_token allows you to specify tokens manually. While you can use # it with +# vnodes (num_tokens > 1, above) -- in which case you should provide a +# comma-separated list -- it's primarily used when adding nodes # to legacy clusters +# that do not have vnodes enabled. +# initial_token: + +# See http://wiki.apache.org/cassandra/HintedHandoff +# May either be "true" or "false" to enable globally +hinted_handoff_enabled: true +# When hinted_handoff_enabled is true, a black list of data centers that will not +# perform hinted handoff +#hinted_handoff_disabled_datacenters: +# - DC1 +# - DC2 +# this defines the maximum amount of time a dead host will have hints +# generated. After it has been dead this long, new hints for it will not be +# created until it has been seen alive and gone down again. +max_hint_window_in_ms: 10800000 # 3 hours + +# Maximum throttle in KBs per second, per delivery thread. This will be +# reduced proportionally to the number of nodes in the cluster. (If there +# are two nodes in the cluster, each delivery thread will use the maximum +# rate; if there are three, each will throttle to half of the maximum, +# since we expect two nodes to be delivering hints simultaneously.) +hinted_handoff_throttle_in_kb: 1024 + +# Number of threads with which to deliver hints; +# Consider increasing this number when you have multi-dc deployments, since +# cross-dc handoff tends to be slower +max_hints_delivery_threads: 2 + +# Directory where Cassandra should store hints. +# If not set, the default directory is $CASSANDRA_HOME/data/hints. +# hints_directory: /var/lib/cassandra/hints + +# How often hints should be flushed from the internal buffers to disk. +# Will *not* trigger fsync. +hints_flush_period_in_ms: 10000 + +# Maximum size for a single hints file, in megabytes. +max_hints_file_size_in_mb: 128 + +# Compression to apply to the hint files. If omitted, hints files +# will be written uncompressed. LZ4, Snappy, and Deflate compressors +# are supported. +#hints_compression: +# - class_name: LZ4Compressor +# parameters: +# - + +# Maximum throttle in KBs per second, total. This will be +# reduced proportionally to the number of nodes in the cluster. +batchlog_replay_throttle_in_kb: 1024 + +# Authentication backend, implementing IAuthenticator; used to identify users +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator, +# PasswordAuthenticator}. +# +# - AllowAllAuthenticator performs no checks - set it to disable authentication. +# - PasswordAuthenticator relies on username/password pairs to authenticate +# users. It keeps usernames and hashed passwords in system_auth.roles table. +# Please increase system_auth keyspace replication factor if you use this authenticator. +# If using PasswordAuthenticator, CassandraRoleManager must also be used (see below) +authenticator: PasswordAuthenticator + +# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer, +# CassandraAuthorizer}. +# +# - AllowAllAuthorizer allows any action to any user - set it to disable authorization. +# - CassandraAuthorizer stores permissions in system_auth.role_permissions table. Please +# increase system_auth keyspace replication factor if you use this authorizer. +authorizer: CassandraAuthorizer + +# Part of the Authentication & Authorization backend, implementing IRoleManager; used +# to maintain grants and memberships between roles. +# Out of the box, Cassandra provides org.apache.cassandra.auth.CassandraRoleManager, +# which stores role information in the system_auth keyspace. Most functions of the +# IRoleManager require an authenticated login, so unless the configured IAuthenticator +# actually implements authentication, most of this functionality will be unavailable. +# +# - CassandraRoleManager stores role data in the system_auth keyspace. Please +# increase system_auth keyspace replication factor if you use this role manager. +role_manager: CassandraRoleManager + +# Validity period for roles cache (fetching permissions can be an +# expensive operation depending on the authorizer). Granted roles are cached for +# authenticated sessions in AuthenticatedUser and after the period specified +# here, become eligible for (async) reload. +# Defaults to 2000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthenticator. +roles_validity_in_ms: 2000 + +# Refresh interval for roles cache (if enabled). +# After this interval, cache entries become eligible for refresh. Upon next +# access, an async reload is scheduled and the old value returned until it +# completes. If roles_validity_in_ms is non-zero, then this must be +# also. +# Defaults to the same value as roles_validity_in_ms. +# roles_update_interval_in_ms: 1000 + +# Validity period for permissions cache (fetching permissions can be an +# expensive operation depending on the authorizer, CassandraAuthorizer is +# one example). Defaults to 2000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthorizer. +permissions_validity_in_ms: 2000 + +# Refresh interval for permissions cache (if enabled). +# After this interval, cache entries become eligible for refresh. Upon next +# access, an async reload is scheduled and the old value returned until it +# completes. If permissions_validity_in_ms is non-zero, then this must be +# also. +# Defaults to the same value as permissions_validity_in_ms. +# permissions_update_interval_in_ms: 1000 + +# The partitioner is responsible for distributing groups of rows (by +# partition key) across nodes in the cluster. You should leave this +# alone for new clusters. The partitioner can NOT be changed without +# reloading all data, so when upgrading you should set this to the +# same partitioner you were already using. +# +# Besides Murmur3Partitioner, partitioners included for backwards +# compatibility include RandomPartitioner, ByteOrderedPartitioner, and +# OrderPreservingPartitioner. +# +partitioner: org.apache.cassandra.dht.Murmur3Partitioner + +# Directories where Cassandra should store data on disk. Cassandra +# will spread data evenly across them, subject to the granularity of +# the configured compaction strategy. +# If not set, the default directory is $CASSANDRA_HOME/data/data. +data_file_directories: + - /var/lib/cassandra/data + +# commit log. when running on magnetic HDD, this should be a +# separate spindle than the data directories. +# If not set, the default directory is $CASSANDRA_HOME/data/commitlog. +commitlog_directory: /var/lib/cassandra/commitlog + +# policy for data disk failures: +# die: shut down gossip and client transports and kill the JVM for any fs errors or +# single-sstable errors, so the node can be replaced. +# stop_paranoid: shut down gossip and client transports even for single-sstable errors, +# kill the JVM for errors during startup. +# stop: shut down gossip and client transports, leaving the node effectively dead, but +# can still be inspected via JMX, kill the JVM for errors during startup. +# best_effort: stop using the failed disk and respond to requests based on +# remaining available sstables. This means you WILL see obsolete +# data at CL.ONE! +# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra +disk_failure_policy: stop + +# policy for commit disk failures: +# die: shut down gossip and Thrift and kill the JVM, so the node can be replaced. +# stop: shut down gossip and Thrift, leaving the node effectively dead, but +# can still be inspected via JMX. +# stop_commit: shutdown the commit log, letting writes collect but +# continuing to service reads, as in pre-2.0.5 Cassandra +# ignore: ignore fatal errors and let the batches fail +commit_failure_policy: stop + +# Maximum size of the key cache in memory. +# +# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the +# minimum, sometimes more. The key cache is fairly tiny for the amount of +# time it saves, so it's worthwhile to use it at large numbers. +# The row cache saves even more time, but must contain the entire row, +# so it is extremely space-intensive. It's best to only use the +# row cache if you have hot rows or static rows. +# +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. +key_cache_size_in_mb: + +# Duration in seconds after which Cassandra should +# save the key cache. Caches are saved to saved_caches_directory as +# specified in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 14400 or 4 hours. +key_cache_save_period: 14400 + +# Number of keys from the key cache to save +# Disabled by default, meaning all keys are going to be saved +# key_cache_keys_to_save: 100 + +# Row cache implementation class name. +# Available implementations: +# org.apache.cassandra.cache.OHCProvider Fully off-heap row cache implementation (default). +# org.apache.cassandra.cache.SerializingCacheProvider This is the row cache implementation availabile +# in previous releases of Cassandra. +# row_cache_class_name: org.apache.cassandra.cache.OHCProvider + +# Maximum size of the row cache in memory. +# Please note that OHC cache implementation requires some additional off-heap memory to manage +# the map structures and some in-flight memory during operations before/after cache entries can be +# accounted against the cache capacity. This overhead is usually small compared to the whole capacity. +# Do not specify more memory that the system can afford in the worst usual situation and leave some +# headroom for OS block level cache. Do never allow your system to swap. +# +# Default value is 0, to disable row caching. +row_cache_size_in_mb: 0 + +# Duration in seconds after which Cassandra should save the row cache. +# Caches are saved to saved_caches_directory as specified in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 0 to disable saving the row cache. +row_cache_save_period: 0 + +# Number of keys from the row cache to save. +# Specify 0 (which is the default), meaning all keys are going to be saved +# row_cache_keys_to_save: 100 + +# Maximum size of the counter cache in memory. +# +# Counter cache helps to reduce counter locks' contention for hot counter cells. +# In case of RF = 1 a counter cache hit will cause Cassandra to skip the read before +# write entirely. With RF > 1 a counter cache hit will still help to reduce the duration +# of the lock hold, helping with hot counter cell updates, but will not allow skipping +# the read entirely. Only the local (clock, count) tuple of a counter cell is kept +# in memory, not the whole counter, so it's relatively cheap. +# +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is empty to make it "auto" (min(2.5% of Heap (in MB), 50MB)). Set to 0 to disable counter cache. +# NOTE: if you perform counter deletes and rely on low gcgs, you should disable the counter cache. +counter_cache_size_in_mb: + +# Duration in seconds after which Cassandra should +# save the counter cache (keys only). Caches are saved to saved_caches_directory as +# specified in this configuration file. +# +# Default is 7200 or 2 hours. +counter_cache_save_period: 7200 + +# Number of keys from the counter cache to save +# Disabled by default, meaning all keys are going to be saved +# counter_cache_keys_to_save: 100 + +# saved caches +# If not set, the default directory is $CASSANDRA_HOME/data/saved_caches. +saved_caches_directory: /var/lib/cassandra/saved_caches + +# commitlog_sync may be either "periodic" or "batch." +# +# When in batch mode, Cassandra won't ack writes until the commit log +# has been fsynced to disk. It will wait +# commitlog_sync_batch_window_in_ms milliseconds between fsyncs. +# This window should be kept short because the writer threads will +# be unable to do extra work while waiting. (You may need to increase +# concurrent_writes for the same reason.) +# +# commitlog_sync: batch +# commitlog_sync_batch_window_in_ms: 2 +# +# the other option is "periodic" where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 + +# The size of the individual commitlog file segments. A commitlog +# segment may be archived, deleted, or recycled once all the data +# in it (potentially from each columnfamily in the system) has been +# flushed to sstables. +# +# The default size is 32, which is almost always fine, but if you are +# archiving commitlog segments (see commitlog_archiving.properties), +# then you probably want a finer granularity of archiving; 8 or 16 MB +# is reasonable. +# Max mutation size is also configurable via max_mutation_size_in_kb setting in +# cassandra.yaml. The default is half the size commitlog_segment_size_in_mb * 1024. +# This should be positive and less than 2048. +# +# NOTE: If max_mutation_size_in_kb is set explicitly then commitlog_segment_size_in_mb must +# be set to at least twice the size of max_mutation_size_in_kb / 1024 +# +commitlog_segment_size_in_mb: 32 + +# Compression to apply to the commit log. If omitted, the commit log +# will be written uncompressed. LZ4, Snappy, and Deflate compressors +# are supported. +#commitlog_compression: +# - class_name: LZ4Compressor +# parameters: +# - + +# any class that implements the SeedProvider interface and has a +# constructor that takes a Map<String, String> of parameters will do. +seed_provider: + # Addresses of hosts that are deemed contact points. + # Cassandra nodes use this list of hosts to find each other and learn + # the topology of the ring. You must change this if you are running + # multiple nodes! + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # seeds is actually a comma-delimited list of addresses. + # Ex: "<ip1>,<ip2>,<ip3>" + - seeds: "127.0.0.1" + +# For workloads with more data than can fit in memory, Cassandra's +# bottleneck will be reads that need to fetch data from +# disk. "concurrent_reads" should be set to (16 * number_of_drives) in +# order to allow the operations to enqueue low enough in the stack +# that the OS and drives can reorder them. Same applies to +# "concurrent_counter_writes", since counter writes read the current +# values before incrementing and writing them back. +# +# On the other hand, since writes are almost never IO bound, the ideal +# number of "concurrent_writes" is dependent on the number of cores in +# your system; (8 * number_of_cores) is a good rule of thumb. +concurrent_reads: 32 +concurrent_writes: 32 +concurrent_counter_writes: 32 + +# For materialized view writes, as there is a read involved, so this should +# be limited by the less of concurrent reads or concurrent writes. +concurrent_materialized_view_writes: 32 + +# Maximum memory to use for pooling sstable buffers. Defaults to the smaller +# of 1/4 of heap or 512MB. This pool is allocated off-heap, so is in addition +# to the memory allocated for heap. Memory is only allocated as needed. +# file_cache_size_in_mb: 512 + +# Flag indicating whether to allocate on or off heap when the sstable buffer +# pool is exhausted, that is when it has exceeded the maximum memory +# file_cache_size_in_mb, beyond which it will not cache buffers but allocate on request. + +# buffer_pool_use_heap_if_exhausted: true + +# The strategy for optimizing disk read +# Possible values are: +# ssd (for solid state disks, the default) +# spinning (for spinning disks) +# disk_optimization_strategy: ssd + +# Total permitted memory to use for memtables. Cassandra will stop +# accepting writes when the limit is exceeded until a flush completes, +# and will trigger a flush based on memtable_cleanup_threshold +# If omitted, Cassandra will set both to 1/4 the size of the heap. +# memtable_heap_space_in_mb: 2048 +# memtable_offheap_space_in_mb: 2048 + +# Ratio of occupied non-flushing memtable size to total permitted size +# that will trigger a flush of the largest memtable. Larger mct will +# mean larger flushes and hence less compaction, but also less concurrent +# flush activity which can make it difficult to keep your disks fed +# under heavy write load. +# +# memtable_cleanup_threshold defaults to 1 / (memtable_flush_writers + 1) +# memtable_cleanup_threshold: 0.11 + +# Specify the way Cassandra allocates and manages memtable memory. +# Options are: +# heap_buffers: on heap nio buffers +# +# Note: offheap_buffers are not supported in Cassandra 3.0 - 3.3. +# They have been re-introduced in Cassandra 3.4. For details see +# https://issues.apache.org/jira/browse/CASSANDRA-9472 and +# https://issues.apache.org/jira/browse/CASSANDRA-11039 +memtable_allocation_type: heap_buffers + +# Total space to use for commit logs on disk. +# +# If space gets above this value, Cassandra will flush every dirty CF +# in the oldest segment and remove it. So a small total commitlog space +# will tend to cause more flush activity on less-active columnfamilies. +# +# The default value is the smaller of 8192, and 1/4 of the total space +# of the commitlog volume. +# +# commitlog_total_space_in_mb: 8192 + +# This sets the amount of memtable flush writer threads. These will +# be blocked by disk io, and each one will hold a memtable in memory +# while blocked. +# +# memtable_flush_writers defaults to the smaller of (number of disks, +# number of cores), with a minimum of 2 and a maximum of 8. +# +# If your data directories are backed by SSD, you should increase this +# to the number of cores. +#memtable_flush_writers: 8 + +# A fixed memory pool size in MB for for SSTable index summaries. If left +# empty, this will default to 5% of the heap size. If the memory usage of +# all index summaries exceeds this limit, SSTables with low read rates will +# shrink their index summaries in order to meet this limit. However, this +# is a best-effort process. In extreme conditions Cassandra may need to use +# more than this amount of memory. +index_summary_capacity_in_mb: + +# How frequently index summaries should be resampled. This is done +# periodically to redistribute memory from the fixed-size pool to sstables +# proportional their recent read rates. Setting to -1 will disable this +# process, leaving existing index summaries at their current sampling level. +index_summary_resize_interval_in_minutes: 60 + +# Whether to, when doing sequential writing, fsync() at intervals in +# order to force the operating system to flush the dirty +# buffers. Enable this to avoid sudden dirty buffer flushing from +# impacting read latencies. Almost always a good idea on SSDs; not +# necessarily on platters. +trickle_fsync: false +trickle_fsync_interval_in_kb: 10240 + +# TCP port, for commands and data +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +storage_port: 7000 + +# SSL port, for encrypted communication. Unused unless enabled in +# encryption_options +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +ssl_storage_port: 7001 + +# Address or interface to bind to and tell other Cassandra nodes to connect to. +# You _must_ change this if you want multiple nodes to be able to communicate! +# +# Set listen_address OR listen_interface, not both. Interfaces must correspond +# to a single address, IP aliasing is not supported. +# +# Leaving it blank leaves it up to InetAddress.getLocalHost(). This +# will always do the Right Thing _if_ the node is properly configured +# (hostname, name resolution, etc), and the Right Thing is to use the +# address associated with the hostname (it might not be). +# +# Setting listen_address to 0.0.0.0 is always wrong. +# +# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address +# you can specify which should be chosen using listen_interface_prefer_ipv6. If false the first ipv4 +# address will be used. If true the first ipv6 address will be used. Defaults to false preferring +# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6. +listen_address: localhost +# listen_interface: eth0 +# listen_interface_prefer_ipv6: false + +# Address to broadcast to other Cassandra nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + +# When using multiple physical network interfaces, set this +# to true to listen on broadcast_address in addition to +# the listen_address, allowing nodes to communicate in both +# interfaces. +# Ignore this property if the network configuration automatically +# routes between the public and private networks such as EC2. +# listen_on_broadcast_address: false + +# Internode authentication backend, implementing IInternodeAuthenticator; +# used to allow/disallow connections from peer nodes. +# internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator + +# Whether to start the native transport server. +# Please note that the address on which the native transport is bound is the +# same as the rpc_address. The port however is different and specified below. +start_native_transport: true +# port for the CQL native transport to listen for clients on +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +native_transport_port: 9042 +# Enabling native transport encryption in client_encryption_options allows you to either use +# encryption for the standard port or to use a dedicated, additional port along with the unencrypted +# standard native_transport_port. +# Enabling client encryption and keeping native_transport_port_ssl disabled will use encryption +# for native_transport_port. Setting native_transport_port_ssl to a different value +# from native_transport_port will use encryption for native_transport_port_ssl while +# keeping native_transport_port unencrypted. +# native_transport_port_ssl: 9142 +# The maximum threads for handling requests when the native transport is used. +# This is similar to rpc_max_threads though the default differs slightly (and +# there is no native_transport_min_threads, idle threads will always be stopped +# after 30 seconds). +# native_transport_max_threads: 128 +# +# The maximum size of allowed frame. Frame (requests) larger than this will +# be rejected as invalid. The default is 256MB. If you're changing this parameter, +# you may want to adjust max_value_size_in_mb accordingly. This should be positive and less than 2048. +# native_transport_max_frame_size_in_mb: 256 + +# The maximum number of concurrent client connections. +# The default is -1, which means unlimited. +# native_transport_max_concurrent_connections: -1 + +# The maximum number of concurrent client connections per source ip. +# The default is -1, which means unlimited. +# native_transport_max_concurrent_connections_per_ip: -1 + +# Whether to start the thrift rpc server. +start_rpc: false + +# The address or interface to bind the Thrift RPC service and native transport +# server to. +# +# Set rpc_address OR rpc_interface, not both. Interfaces must correspond +# to a single address, IP aliasing is not supported. +# +# Leaving rpc_address blank has the same effect as on listen_address +# (i.e. it will be based on the configured hostname of the node). +# +# Note that unlike listen_address, you can specify 0.0.0.0, but you must also +# set broadcast_rpc_address to a value other than 0.0.0.0. +# +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +# +# If you choose to specify the interface by name and the interface has an ipv4 and an ipv6 address +# you can specify which should be chosen using rpc_interface_prefer_ipv6. If false the first ipv4 +# address will be used. If true the first ipv6 address will be used. Defaults to false preferring +# ipv4. If there is only one address it will be selected regardless of ipv4/ipv6. +rpc_address: localhost +# rpc_interface: eth1 +# rpc_interface_prefer_ipv6: false + +# port for Thrift to listen for clients on +rpc_port: 9160 + +# RPC address to broadcast to drivers and other Cassandra nodes. This cannot +# be set to 0.0.0.0. If left blank, this will be set to the value of +# rpc_address. If rpc_address is set to 0.0.0.0, broadcast_rpc_address must +# be set. +# broadcast_rpc_address: 1.2.3.4 + +# enable or disable keepalive on rpc/native connections +rpc_keepalive: true + +# Cassandra provides two out-of-the-box options for the RPC Server: +# +# sync -> One thread per thrift connection. For a very large number of clients, memory +# will be your limiting factor. On a 64 bit JVM, 180KB is the minimum stack size +# per thread, and that will correspond to your use of virtual memory (but physical memory +# may be limited depending on use of stack space). +# +# hsha -> Stands for "half synchronous, half asynchronous." All thrift clients are handled +# asynchronously using a small number of threads that does not vary with the amount +# of thrift clients (and thus scales well to many clients). The rpc requests are still +# synchronous (one thread per active request). If hsha is selected then it is essential +# that rpc_max_threads is changed from the default value of unlimited. +# +# The default is sync because on Windows hsha is about 30% slower. On Linux, +# sync/hsha performance is about the same, with hsha of course using less memory. +# +# Alternatively, can provide your own RPC server by providing the fully-qualified class name +# of an o.a.c.t.TServerFactory that can create an instance of it. +rpc_server_type: sync + +# Uncomment rpc_min|max_thread to set request pool size limits. +# +# Regardless of your choice of RPC server (see above), the number of maximum requests in the +# RPC thread pool dictates how many concurrent requests are possible (but if you are using the sync +# RPC server, it also dictates the number of clients that can be connected at all). +# +# The default is unlimited and thus provides no protection against clients overwhelming the server. You are +# encouraged to set a maximum that makes sense for you in production, but do keep in mind that +# rpc_max_threads represents the maximum number of client requests this server may execute concurrently. +# +# rpc_min_threads: 16 +# rpc_max_threads: 2048 + +# uncomment to set socket buffer sizes on rpc connections +# rpc_send_buff_size_in_bytes: +# rpc_recv_buff_size_in_bytes: + +# Uncomment to set socket buffer size for internode communication +# Note that when setting this, the buffer size is limited by net.core.wmem_max +# and when not setting it it is defined by net.ipv4.tcp_wmem +# See: +# /proc/sys/net/core/wmem_max +# /proc/sys/net/core/rmem_max +# /proc/sys/net/ipv4/tcp_wmem +# /proc/sys/net/ipv4/tcp_wmem +# and: man tcp +# internode_send_buff_size_in_bytes: +# internode_recv_buff_size_in_bytes: + +# Frame size for thrift (maximum message length). +thrift_framed_transport_size_in_mb: 15 + +# Set to true to have Cassandra create a hard link to each sstable +# flushed or streamed locally in a backups/ subdirectory of the +# keyspace data. Removing these links is the operator's +# responsibility. +incremental_backups: false + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Cassandra won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +snapshot_before_compaction: false + +# Whether or not a snapshot is taken of the data before keyspace truncation +# or dropping of column families. The STRONGLY advised default of true +# should be used to provide data safety. If you set this flag to false, you will +# lose data on truncation or drop. +auto_snapshot: true + +# When executing a scan, within or across a partition, we need to keep the +# tombstones seen in memory so we can return them to the coordinator, which +# will use them to make sure other replicas also know about the deleted rows. +# With workloads that generate a lot of tombstones, this can cause performance +# problems and even exaust the server heap. +# (http://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets) +# Adjust the thresholds here if you understand the dangers and want to +# scan more tombstones anyway. These thresholds may also be adjusted at runtime +# using the StorageService mbean. +tombstone_warn_threshold: 1000 +tombstone_failure_threshold: 100000 + +# Granularity of the collation index of rows within a partition. +# Increase if your rows are large, or if you have a very large +# number of rows per partition. The competing goals are these: +# 1) a smaller granularity means more index entries are generated +# and looking up rows withing the partition by collation column +# is faster +# 2) but, Cassandra will keep the collation index in memory for hot +# rows (as part of the key cache), so a larger granularity means +# you can cache more hot rows +column_index_size_in_kb: 64 + + +# Log WARN on any batch size exceeding this value. 5kb per batch by default. +# Caution should be taken on increasing the size of this threshold as it can lead to node instability. +batch_size_warn_threshold_in_kb: 5 + +# Fail any batch exceeding this value. 50kb (10x warn threshold) by default. +batch_size_fail_threshold_in_kb: 50 + +# Log WARN on any batches not of type LOGGED than span across more partitions than this limit +unlogged_batch_across_partitions_warn_threshold: 10 + +# Number of simultaneous compactions to allow, NOT including +# validation "compactions" for anti-entropy repair. Simultaneous +# compactions can help preserve read performance in a mixed read/write +# workload, by mitigating the tendency of small sstables to accumulate +# during a single long running compactions. The default is usually +# fine and if you experience problems with compaction running too +# slowly or too fast, you should look at +# compaction_throughput_mb_per_sec first. +# +# concurrent_compactors defaults to the smaller of (number of disks, +# number of cores), with a minimum of 2 and a maximum of 8. +# +# If your data directories are backed by SSD, you should increase this +# to the number of cores. +#concurrent_compactors: 1 + +# Throttles compaction to the given total throughput across the entire +# system. The faster you insert data, the faster you need to compact in +# order to keep the sstable count down, but in general, setting this to +# 16 to 32 times the rate you are inserting data is more than sufficient. +# Setting this to 0 disables throttling. Note that this account for all types +# of compaction, including validation compaction. +compaction_throughput_mb_per_sec: 16 + +# Log a warning when compacting partitions larger than this value +compaction_large_partition_warning_threshold_mb: 100 + +# When compacting, the replacement sstable(s) can be opened before they +# are completely written, and used in place of the prior sstables for +# any range that has been written. This helps to smoothly transfer reads +# between the sstables, reducing page cache churn and keeping hot rows hot +sstable_preemptive_open_interval_in_mb: 50 + +# Throttles all outbound streaming file transfers on this node to the +# given total throughput in Mbps. This is necessary because Cassandra does +# mostly sequential IO when streaming data during bootstrap or repair, which +# can lead to saturating the network connection and degrading rpc performance. +# When unset, the default is 200 Mbps or 25 MB/s. +# stream_throughput_outbound_megabits_per_sec: 200 + +# Throttles all streaming file transfer between the datacenters, +# this setting allows users to throttle inter dc stream throughput in addition +# to throttling all network stream traffic as configured with +# stream_throughput_outbound_megabits_per_sec +# When unset, the default is 200 Mbps or 25 MB/s +# inter_dc_stream_throughput_outbound_megabits_per_sec: 200 + +# How long the coordinator should wait for read operations to complete +read_request_timeout_in_ms: 5000 +# How long the coordinator should wait for seq or index scans to complete +range_request_timeout_in_ms: 10000 +# How long the coordinator should wait for writes to complete +write_request_timeout_in_ms: 2000 +# How long the coordinator should wait for counter writes to complete +counter_write_request_timeout_in_ms: 5000 +# How long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +cas_contention_timeout_in_ms: 1000 +# How long the coordinator should wait for truncates to complete +# (This can be much longer, because unless auto_snapshot is disabled +# we need to flush first so we can snapshot before removing the data.) +truncate_request_timeout_in_ms: 60000 +# The default timeout for other, miscellaneous operations +request_timeout_in_ms: 10000 + +# Enable operation timeout information exchange between nodes to accurately +# measure request timeouts. If disabled, replicas will assume that requests +# were forwarded to them instantly by the coordinator, which means that +# under overload conditions we will waste that much extra time processing +# already-timed-out requests. +# +# Warning: before enabling this property make sure to ntp is installed +# and the times are synchronized between the nodes. +cross_node_timeout: false + +# Set socket timeout for streaming operation. +# The stream session is failed if no data/ack is received by any of the participants +# within that period, which means this should also be sufficient to stream a large +# sstable or rebuild table indexes. +# Default value is 86400000ms, which means stale streams timeout after 24 hours. +# A value of zero means stream sockets should never time out. +# streaming_socket_timeout_in_ms: 86400000 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# endpoint_snitch -- Set this to a class that implements +# IEndpointSnitch. The snitch has two functions: +# - it teaches Cassandra enough about your network topology to route +# requests efficiently +# - it allows Cassandra to spread replicas around your cluster to avoid +# correlated failures. It does this by grouping machines into +# "datacenters" and "racks." Cassandra will do its best not to have +# more than one replica on the same "rack" (which may not actually +# be a physical location) +# +# CASSANDRA WILL NOT ALLOW YOU TO SWITCH TO AN INCOMPATIBLE SNITCH +# ONCE DATA IS INSERTED INTO THE CLUSTER. This would cause data loss. +# This means that if you start with the default SimpleSnitch, which +# locates every node on "rack1" in "datacenter1", your only options +# if you need to add another datacenter are GossipingPropertyFileSnitch +# (and the older PFS). From there, if you want to migrate to an +# incompatible snitch like Ec2Snitch you can do it by adding new nodes +# under Ec2Snitch (which will locate them in a new "datacenter") and +# decommissioning the old ones. +# +# Out of the box, Cassandra provides +# - SimpleSnitch: +# Treats Strategy order as proximity. This can improve cache +# locality when disabling read repair. Only appropriate for +# single-datacenter deployments. +# - GossipingPropertyFileSnitch +# This should be your go-to snitch for production use. The rack +# and datacenter for the local node are defined in +# cassandra-rackdc.properties and propagated to other nodes via +# gossip. If cassandra-topology.properties exists, it is used as a +# fallback, allowing migration from the PropertyFileSnitch. +# - PropertyFileSnitch: +# Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-topology.properties. +# - Ec2Snitch: +# Appropriate for EC2 deployments in a single Region. Loads Region +# and Availability Zone information from the EC2 API. The Region is +# treated as the datacenter, and the Availability Zone as the rack. +# Only private IPs are used, so this will not work across multiple +# Regions. +# - Ec2MultiRegionSnitch: +# Uses public IPs as broadcast_address to allow cross-region +# connectivity. (Thus, you should set seed addresses to the public +# IP as well.) You will need to open the storage_port or +# ssl_storage_port on the public IP firewall. (For intra-Region +# traffic, Cassandra will switch to the private IP after +# establishing a connection.) +# - RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's IP +# address, respectively. Unless this happens to match your +# deployment conventions, this is best used as an example of +# writing a custom Snitch class and is provided in that spirit. +# +# You can use a custom Snitch by setting this to the full class name +# of the snitch, which will be assumed to be on your classpath. +endpoint_snitch: SimpleSnitch + +# controls how often to perform the more expensive part of host score +# calculation +dynamic_snitch_update_interval_in_ms: 100 +# controls how often to reset all host scores, allowing a bad host to +# possibly recover +dynamic_snitch_reset_interval_in_ms: 600000 +# if set greater than zero and read_repair_chance is < 1.0, this will allow +# 'pinning' of replicas to hosts in order to increase cache capacity. +# The badness threshold will control how much worse the pinned host has to be +# before the dynamic snitch will prefer other replicas over it. This is +# expressed as a double which represents a percentage. Thus, a value of +# 0.2 means Cassandra would continue to prefer the static snitch values +# until the pinned host was 20% worse than the fastest. +dynamic_snitch_badness_threshold: 0.1 + +# request_scheduler -- Set this to a class that implements +# RequestScheduler, which will schedule incoming client requests +# according to the specific policy. This is useful for multi-tenancy +# with a single Cassandra cluster. +# NOTE: This is specifically for requests from the client and does +# not affect inter node communication. +# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place +# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of +# client requests to a node with a separate queue for each +# request_scheduler_id. The scheduler is further customized by +# request_scheduler_options as described below. +request_scheduler: org.apache.cassandra.scheduler.NoScheduler + +# Scheduler Options vary based on the type of scheduler +# NoScheduler - Has no options +# RoundRobin +# - throttle_limit -- The throttle_limit is the number of in-flight +# requests per client. Requests beyond +# that limit are queued up until +# running requests can complete. +# The value of 80 here is twice the number of +# concurrent_reads + concurrent_writes. +# - default_weight -- default_weight is optional and allows for +# overriding the default which is 1. +# - weights -- Weights are optional and will default to 1 or the +# overridden default_weight. The weight translates into how +# many requests are handled during each turn of the +# RoundRobin, based on the scheduler id. +# +# request_scheduler_options: +# throttle_limit: 80 +# default_weight: 5 +# weights: +# Keyspace1: 1 +# Keyspace2: 5 + +# request_scheduler_id -- An identifier based on which to perform +# the request scheduling. Currently the only valid option is keyspace. +# request_scheduler_id: keyspace + +# Enable or disable inter-node encryption +# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that +# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher +# suite for authentication, key exchange and encryption of the actual data transfers. +# Use the DHE/ECDHE ciphers if running in FIPS 140 compliant mode. +# NOTE: No custom encryption options are enabled at the moment +# The available internode options are : all, none, dc, rack +# +# If set to dc cassandra will encrypt the traffic between the DCs +# If set to rack cassandra will encrypt the traffic between the racks +# +# The passwords used in these options must match the passwords used when generating +# the keystore and truststore. For instructions on generating these files, see: +# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore +# +server_encryption_options: + internode_encryption: none + keystore: conf/.keystore + keystore_password: cassandra + truststore: conf/.truststore + truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA] + # require_client_auth: false + +# enable or disable client/server encryption. +client_encryption_options: + enabled: false + # If enabled and optional is set to true encrypted and unencrypted connections are handled. + optional: false + keystore: conf/.keystore + keystore_password: cassandra + # require_client_auth: false + # Set trustore and truststore_password if require_client_auth is true + # truststore: conf/.truststore + # truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA] + +# internode_compression controls whether traffic between nodes is +# compressed. +# can be: all - all traffic is compressed +# dc - traffic between different datacenters is compressed +# none - nothing is compressed. +internode_compression: all + +# Enable or disable tcp_nodelay for inter-dc communication. +# Disabling it will result in larger (but fewer) network packets being sent, +# reducing overhead from the TCP protocol itself, at the cost of increasing +# latency if you block for cross-datacenter responses. +inter_dc_tcp_nodelay: false + +# TTL for different trace types used during logging of the repair process. +tracetype_query_ttl: 86400 +tracetype_repair_ttl: 604800 + +# By default, Cassandra logs GC Pauses greater than 200 ms at INFO level +# This threshold can be adjusted to minimize logging if necessary +# gc_log_threshold_in_ms: 200 + +# GC Pauses greater than gc_warn_threshold_in_ms will be logged at WARN level +# If unset, all GC Pauses greater than gc_log_threshold_in_ms will log at +# INFO level +# Adjust the threshold based on your application throughput requirement +gc_warn_threshold_in_ms: 1000 + +# UDFs (user defined functions) are disabled by default. +# As of Cassandra 3.0 there is a sandbox in place that should prevent execution of evil code. +enable_user_defined_functions: false + +# Enables scripted UDFs (JavaScript UDFs). +# Java UDFs are always enabled, if enable_user_defined_functions is true. +# Enable this option to be able to use UDFs with "language javascript" or any custom JSR-223 provider. +# This option has no effect, if enable_user_defined_functions is false. +enable_scripted_user_defined_functions: false + +# The default Windows kernel timer and scheduling resolution is 15.6ms for power conservation. +# Lowering this value on Windows can provide much tighter latency and better throughput, however +# some virtualized environments may see a negative performance impact from changing this setting +# below their system default. The sysinternals 'clockres' tool can confirm your system's default +# setting. +windows_timer_interval: 1 + +# Maximum size of any value in SSTables. Safety measure to detect SSTable corruption +# early. Any value size larger than this threshold will result into marking an SSTable +# as corrupted. This should be positive and less than 2048. +# max_value_size_in_mb: 256 + +# Coalescing Strategies # +# Coalescing multiples messages turns out to significantly boost message processing throughput (think doubling or more). +# On bare metal, the floor for packet processing throughput is high enough that many applications won't notice, but in +# virtualized environments, the point at which an application can be bound by network packet processing can be +# surprisingly low compared to the throughput of task processing that is possible inside a VM. It's not that bare metal +# doesn't benefit from coalescing messages, it's that the number of packets a bare metal network interface can process +# is sufficient for many applications such that no load starvation is experienced even without coalescing. +# There are other benefits to coalescing network messages that are harder to isolate with a simple metric like messages +# per second. By coalescing multiple tasks together, a network thread can process multiple messages for the cost of one +# trip to read from a socket, and all the task submission work can be done at the same time reducing context switching +# and increasing cache friendliness of network message processing. +# See CASSANDRA-8692 for details. + +# Strategy to use for coalescing messages in OutboundTcpConnection. +# Can be fixed, movingaverage, timehorizon (default), disabled. +# You can also specify a subclass of CoalescingStrategies.CoalescingStrategy by name. +# otc_coalescing_strategy: TIMEHORIZON + +# How many microseconds to wait for coalescing. For fixed strategy this is the amount of time after the first +# message is received before it will be sent with any accompanying messages. For moving average this is the +# maximum amount of time that will be waited as well as the interval at which messages must arrive on average +# for coalescing to be enabled. +# otc_coalescing_window_us: 200 + +# Do not try to coalesce messages if we already got that many messages. This should be more than 2 and less than 128. +# otc_coalescing_enough_coalesced_messages: 8 + +# How many milliseconds to wait between two expiration runs on the backlog (queue) of the OutboundTcpConnection. +# Expiration is done if messages are piling up in the backlog. Droppable messages are expired to free the memory +# taken by expired messages. The interval should be between 0 and 1000, and in most installations the default value +# will be appropriate. A smaller value could potentially expire messages slightly sooner at the expense of more CPU +# time and queue contention while iterating the backlog of messages. +# An interval of 0 disables any wait time, which is the behavior of former Cassandra versions. +# +# otc_backlog_expiration_interval_ms: 200 diff --git a/distribution/cassandra/docker-entrypoint.sh b/distribution/cassandra/docker-entrypoint.sh new file mode 100644 index 00000000..cec4587b --- /dev/null +++ b/distribution/cassandra/docker-entrypoint.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -e + +# first arg is `-f` or `--some-option` +# or there are no args +if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then + set -- cassandra -f "$@" +fi + +# allow the container to be started with `--user` +if [ "$1" = 'cassandra' -a "$(id -u)" = '0' ]; then + chown -R cassandra /var/lib/cassandra /var/log/cassandra "$CASSANDRA_CONFIG" + exec gosu cassandra "$BASH_SOURCE" "$@" +fi + +if [ "$1" = 'cassandra' ]; then + : ${CASSANDRA_RPC_ADDRESS='0.0.0.0'} + + : ${CASSANDRA_LISTEN_ADDRESS='auto'} + if [ "$CASSANDRA_LISTEN_ADDRESS" = 'auto' ]; then + CASSANDRA_LISTEN_ADDRESS="$(hostname --ip-address)" + fi + + : ${CASSANDRA_BROADCAST_ADDRESS="$CASSANDRA_LISTEN_ADDRESS"} + + if [ "$CASSANDRA_BROADCAST_ADDRESS" = 'auto' ]; then + CASSANDRA_BROADCAST_ADDRESS="$(hostname --ip-address)" + fi + : ${CASSANDRA_BROADCAST_RPC_ADDRESS:=$CASSANDRA_BROADCAST_ADDRESS} + + if [ -n "${CASSANDRA_NAME:+1}" ]; then + : ${CASSANDRA_SEEDS:="cassandra"} + fi + : ${CASSANDRA_SEEDS:="$CASSANDRA_BROADCAST_ADDRESS"} + + sed -ri 's/(- seeds:).*/\1 "'"$CASSANDRA_SEEDS"'"/' "$CASSANDRA_CONFIG/cassandra.yaml" + + for yaml in \ + broadcast_address \ + broadcast_rpc_address \ + cluster_name \ + endpoint_snitch \ + listen_address \ + num_tokens \ + rpc_address \ + start_rpc \ + ; do + var="CASSANDRA_${yaml^^}" + val="${!var}" + if [ "$val" ]; then + sed -ri 's/^(# )?('"$yaml"':).*/\2 '"$val"'/' "$CASSANDRA_CONFIG/cassandra.yaml" + fi + done + + for rackdc in dc rack; do + var="CASSANDRA_${rackdc^^}" + val="${!var}" + if [ "$val" ]; then + sed -ri 's/^('"$rackdc"'=).*/\1 '"$val"'/' "$CASSANDRA_CONFIG/cassandra-rackdc.properties" + fi + done +fi + +for f in /docker-entrypoint-initdb.d/*.cql; do + if [ "${CASSUSER}" ]; then + sed -ri 's/CASSUSER/'${CASSUSER}'/' "$f" + fi + if [ "${CASSPASS}" ]; then + sed -ri 's/CASSPASS/'${CASSPASS}'/' "$f" + fi +done + + + + +echo "################################ Let run Scripts ##############################" +for f in /docker-entrypoint-initdb.d/*; do + + case "$f" in + *.cql) + echo "$0: running $f" && until cqlsh -u cassandra -p cassandra -f "$f"; do >&2 echo "Cassandra is unavailable - sleeping"; sleep 2; done & ;; + *) echo "$0: ignoring $f" ;; + esac + echo +done +echo "################################ Let run Scripts End ##############################" + +exec "$@" diff --git a/distribution/cassandra/music.cql b/distribution/cassandra/music.cql new file mode 100644 index 00000000..d991a514 --- /dev/null +++ b/distribution/cassandra/music.cql @@ -0,0 +1,20 @@ +CREATE KEYSPACE admin + WITH REPLICATION = { + 'class' : 'SimpleStrategy', + 'replication_factor': 1 + } + AND DURABLE_WRITES = true; + +CREATE TABLE admin.keyspace_master ( + uuid uuid, + keyspace_name text, + application_name text, + is_api boolean, + password text, + username text, + is_aaf boolean, + PRIMARY KEY (uuid) +); + +CREATE USER nelson24 WITH PASSWORD ‘winman123’ SUPERUSER; +ALTER USER cassandra WITH PASSWORD ‘SomeLongRandomStringNoonewillthinkof’; diff --git a/distribution/cassandra/music_single.cql b/distribution/cassandra/music_single.cql new file mode 100644 index 00000000..b8a60cd1 --- /dev/null +++ b/distribution/cassandra/music_single.cql @@ -0,0 +1,20 @@ +CREATE KEYSPACE IF NOT EXISTS admin + WITH REPLICATION = { + 'class' : 'SimpleStrategy', + 'replication_factor': 1 + } + AND DURABLE_WRITES = true; + +CREATE TABLE IF NOT EXISTS admin.keyspace_master ( + uuid uuid, + keyspace_name text, + application_name text, + is_api boolean, + password text, + username text, + is_aaf boolean, + PRIMARY KEY (uuid) +); + +CREATE ROLE IF NOT EXISTS CASSUSER WITH PASSWORD = 'CASSPASS' AND SUPERUSER = True AND LOGIN = True; +ALTER ROLE cassandra WITH PASSWORD = 'SomeLongRandomStringNoonewillthinkof'; diff --git a/distribution/dockermusic/README.md b/distribution/dockermusic/README.md new file mode 100644 index 00000000..436921b0 --- /dev/null +++ b/distribution/dockermusic/README.md @@ -0,0 +1,17 @@ +### Docker Setup for Single instance of MUSIC + +<p>Please update the <b>properties/music.properties</b> file to fit your env.<br/> +Update the start.sh file.<br/> +The beginning of the <b>start.sh</b> file contains various variables.<br/></p> + +CASS_IMG - Cassandra Image<br/> +TOMCAT_IMG - Tomcat Image<br/> +ZK_IMG - Zookeeper Image<br/> +MUSIC_IMG - Music Image containing the MUSIC war file.<br/> +WORK_DIR - Default to PWD.<br/> +CASS_USERNAME - Username for Cassandra - should match cassandra.user in music.properties +file<br/> +CASS_PASSWORD - Password for Cassandra - should match cassandra.password in music.properties.<br/> + +MUSIC Logs will be saved in logs/MUSIC after start of tomcat.<br/> + diff --git a/distribution/dockermusic/properties/music.properties b/distribution/dockermusic/properties/music.properties new file mode 100644 index 00000000..02ba435c --- /dev/null +++ b/distribution/dockermusic/properties/music.properties @@ -0,0 +1,19 @@ +my.public.ip=localhost +all.public.ips=localhost +my.id=0 +all.ids=0 +####################################### +# Optional current values are defaults +####################################### +zookeeper.host=music-zk +cassandra.host=music-db +#music.ip=localhost +#debug=true +#music.rest.ip=localhost +#lock.lease.period=6000 +cassandra.user=xxuserxxx +cassandra.password=xxpasswordxx +# AAF Endpoint if using AAF +#aaf.endpoint.url= + + diff --git a/distribution/dockermusic/start.sh b/distribution/dockermusic/start.sh new file mode 100644 index 00000000..57b05890 --- /dev/null +++ b/distribution/dockermusic/start.sh @@ -0,0 +1,82 @@ +# +# ------------------------------------------------------------------------- +# Copyright (c) 2017 AT&T Intellectual Property +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------- +# In this example we are building a docker bridge network(music-net) for all +# the containers +# Then we connect the host bridge network(bridge) to the internal network(music-net) +# +# +# +CASS_IMG=nexus3.onap.org:10001/onap/music/cassandra_music:latest +TOMCAT_IMG=nexus3.onap.org:10001/library/tomcat:8.0 +ZK_IMG=nexus3.onap.org:10001/library/zookeeper:3.4 +MUSIC_IMG=nexus3.onap.org:10001/onap/music/music:latest +WORK_DIR=${PWD} +CASS_USERNAME=cassandra1 +CASS_PASSWORD=cassandra1 + +if [ "$1" = "start" ]; then + +# Create Volume for mapping war file and tomcat +docker volume create music-vol; + +# Create a network for all the containers to run in. +docker network create music-net; + +# Start Cassandra +docker run -d --rm --name music-db --network music-net \ +-p "7000:7000" -p "7001:7001" -p "7199:7199" -p "9042:9042" -p "9160:9160" \ +-e CASSNAME=${CASS_USERNAME} \ +-e CASSPASS=${CASS_PASSWORD} \ +${CASS_IMG}; + +# Start Music war +docker run -d --rm --name music-war \ +-v music-vol:/app \ +${MUSIC_IMG}; + +# Start Zookeeper +docker run -d --rm --name music-zk --network music-net +-p "2181:2181" -p "2888:2888" -p "3888:3888" \ +${ZK_IMG}; + +# Delay for Cassandra +sleep 20; + +# Start Up tomcat - Needs to have properties,logs dir and war file volume mapped. +docker run -d --rm --name music-tomcat --network music-net -p "8080:8080" \ +-v music-vol:/usr/local/tomcat/webapps \ +-v ${WORK_DIR}/properties:/opt/app/music/etc:ro \ +-v ${WORK_DIR}/logs:/opt/app/music/logs \ +${TOMCAT_IMG}; + +# Connect tomcat to host bridge network so that its port can be seen. +docker network connect bridge music-tomcat; + +fi + + +# Shutdown and clean up. +if [ "$1" = "stop" ]; then +docker stop music-war; +docker stop music-db; +docker stop music-zk; +docker stop music-tomcat; +docker network rm music-net; +sleep 5; +docker volume rm music-vol; +fi diff --git a/distribution/tomcat/Dockerfile b/distribution/tomcat/Dockerfile new file mode 100644 index 00000000..7d4f2ad9 --- /dev/null +++ b/distribution/tomcat/Dockerfile @@ -0,0 +1,3 @@ +FROM library/tomcat:8.5 +LABEL purpose="Tomcat for MUSIC" + diff --git a/distribution/zookeeper/Dockerfile b/distribution/zookeeper/Dockerfile new file mode 100644 index 00000000..fdc89dc0 --- /dev/null +++ b/distribution/zookeeper/Dockerfile @@ -0,0 +1,3 @@ +FROM library/zookeeper:3.4 +LABEL purpose="For MUSIC" + @@ -1,31 +1,21 @@ -<!-- - ============LICENSE_START========================================== - org.onap.music - =================================================================== - Copyright (c) 2017 AT&T Intellectual Property - =================================================================== - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ============LICENSE_END============================================= - ==================================================================== ---> +<!-- ============LICENSE_START========================================== + org.onap.music =================================================================== + Copyright (c) 2017 AT&T Intellectual Property =================================================================== + Licensed under the Apache License, Version 2.0 (the "License"); you may not + use this file except in compliance with the License. You may obtain a copy + of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required + by applicable law or agreed to in writing, software distributed under the + License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied. See the License for the specific + language governing permissions and limitations under the License. ============LICENSE_END============================================= + ==================================================================== --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.onap.music</groupId> <artifactId>MUSIC</artifactId> <packaging>war</packaging> - <version>2.4.12</version> + <version>2.4.15</version> <description> This is the MUSIC REST interface, packaged as a war file. </description> @@ -42,7 +32,7 @@ <jersey1.version>1.17</jersey1.version> <jersey2.version>2.26</jersey2.version> <jaxrs.version>2.0.1</jaxrs.version> - <cassandra.version>3.0.0</cassandra.version> + <cassandra.version>3.2.0</cassandra.version> <zookeeper.version>3.4.6</zookeeper.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -168,12 +158,11 @@ </build> <dependencies> - + <!-- Logging --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> - <exclusions> <exclusion> <groupId>org.slf4j</groupId> @@ -181,7 +170,6 @@ </exclusion> </exclusions> </dependency> - <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> @@ -193,17 +181,19 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>1.0.1-oss</version> + </dependency> + <!-- End Logging --> <dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>${cassandra.version}</version> </dependency> - <dependency> - <groupId>org.cassandraunit</groupId> - <artifactId>cassandra-unit</artifactId> - <version>3.3.0.2</version> - </dependency> + <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> @@ -215,6 +205,7 @@ </exclusion> </exclusions> </dependency> + <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> @@ -230,61 +221,80 @@ <artifactId>jersey-json</artifactId> <version>${jersey1.version}</version> </dependency> + <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-model</artifactId> - <version>3.3.9</version> - </dependency> + <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> <scope>provided</scope> </dependency> + <!-- <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.maven</groupId> <artifactId>maven-model</artifactId> + <version>3.3.9</version> </dependency> --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-jcs-core</artifactId> <version>2.2</version> </dependency> <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <version>3.0.1</version> - <scope>provided</scope> - </dependency> - <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency> <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.12</version> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey-jaxrs</artifactId> + <version>1.5.8</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>19.0</version> + </dependency> + <!-- Testing --> + <dependency> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit</artifactId> + <version>3.3.0.2</version> <scope>test</scope> </dependency> - <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.0</version> + <scope>test</scope> </dependency> <dependency> - <groupId>io.swagger</groupId> - <artifactId>swagger-jersey-jaxrs</artifactId> - <version>1.5.8</version> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - <version>19.0</version> + <groupId>org.apache.curator</groupId> + <artifactId>curator-test</artifactId> + <version>2.3.0</version> + <exclusions> + <exclusion> + <groupId>org.apache.zookeeper</groupId> + <artifactId>zookeeper</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + </exclusions> + <scope>test</scope> </dependency> - + <!-- Added to force update dependency jars that are not secure Cassandra-Unit + depends on older version that is not secure --> <dependency> - <groupId>com.att.eelf</groupId> - <artifactId>eelf-core</artifactId> - <version>1.0.1-oss</version> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.3</version> </dependency> </dependencies> @@ -324,7 +334,7 @@ <images> <!-- MUSIC War --> <image> - <name>music</name> + <name>onap/music/music</name> <alias>docker_music</alias> <build> <cleanup>true</cleanup> @@ -338,6 +348,49 @@ </assembly> </build> </image> + <!-- Cassandra --> + <image> + <name>onap/music/cassandra_music</name> + <alias>docker_cassandra</alias> + <build> + <cleanup>true</cleanup> + <tags> + <tag>3.0-${timestamp}</tag> + <tag>3.0-latest</tag> + </tags> + <dockerFileDir>${project.basedir}/distribution/cassandra</dockerFileDir> + </build> + </image> + <!-- Zookeeper --> + <!-- + <image> + <name>onap/music/zookeeper_music</name> + <alias>docker_zookeeper</alias> + <build> + <cleanup>true</cleanup> + <tags> + <tag>3.4-${timestamp}</tag> + <tag>3.4-latest</tag> + </tags> + <dockerFileDir>${project.basedir}/distribution/zookeeper</dockerFileDir> + </build> + </image> + --> + <!-- tomcat 8.5 --> + <!-- + <image> + <name>onap/music/tomcat_music</name> + <alias>docker_tomcat</alias> + <build> + <cleanup>true</cleanup> + <tags> + <tag>8.5-${timestamp}</tag> + <tag>8.5-latest</tag> + </tags> + <dockerFileDir>${project.basedir}/distribution/tomcat</dockerFileDir> + </build> + </image>\ + --> </images> </configuration> <executions> @@ -366,12 +419,12 @@ <goal>push</goal> </goals> <configuration> - <image>music</image> + <image>onap/music/music</image> </configuration> </execution> </executions> </plugin> - </plugins> + </plugins> </build> </profile> </profiles> diff --git a/src/main/java/org/onap/music/datastore/MusicDataStore.java b/src/main/java/org/onap/music/datastore/MusicDataStore.java index e1ae5b08..c64a96b3 100644 --- a/src/main/java/org/onap/music/datastore/MusicDataStore.java +++ b/src/main/java/org/onap/music/datastore/MusicDataStore.java @@ -30,6 +30,9 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.main.MusicUtil; @@ -46,6 +49,7 @@ import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; import com.datastax.driver.core.TableMetadata; import com.datastax.driver.core.exceptions.AlreadyExistsException; +import com.datastax.driver.core.exceptions.InvalidQueryException; import com.datastax.driver.core.exceptions.NoHostAvailableException; /** @@ -65,6 +69,13 @@ public class MusicDataStore { public void setSession(Session session) { this.session = session; } + + /** + * @param session + */ + public Session getSession() { + return session; + } /** * @param cluster @@ -124,7 +135,9 @@ public class MusicDataStore { } } } catch (SocketException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.CONNCECTIVITYERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); } return allPossibleIps; } @@ -152,7 +165,7 @@ public class MusicDataStore { break; } catch (NoHostAvailableException e) { address = it.next(); - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.HOSTUNAVAILABLE, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); } } } @@ -179,7 +192,7 @@ public class MusicDataStore { try { session = cluster.connect(); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY, ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE); throw new MusicServiceException( "Error while connecting to Cassandra cluster.. " + ex.getMessage()); } @@ -245,7 +258,7 @@ public class MusicDataStore { } } - public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) { + public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) throws Exception { ColumnDefinitions colInfo = row.getColumnDefinitions(); for (Map.Entry<String, Object> entry : condition.entrySet()) { @@ -301,8 +314,7 @@ public class MusicDataStore { boolean result = false; if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { - logger.error(EELFLoggerDelegate.errorLogger, - "Error while processing prepared query object"); + logger.error(EELFLoggerDelegate.errorLogger, queryObject.getQuery(),AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + queryObject.getQuery() + "]"); } @@ -310,7 +322,14 @@ public class MusicDataStore { "In preprared Execute Put: the actual insert query:" + queryObject.getQuery() + "; the values" + queryObject.getValues()); - PreparedStatement preparedInsert = session.prepare(queryObject.getQuery()); + PreparedStatement preparedInsert = null; + try { + preparedInsert = session.prepare(queryObject.getQuery()); + } catch(InvalidQueryException iqe) { + logger.error(EELFLoggerDelegate.errorLogger, iqe.getMessage()); + throw new MusicQueryException(iqe.getMessage()); + } + try { if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { logger.info(EELFLoggerDelegate.applicationLogger, "Executing critical put query"); @@ -325,13 +344,12 @@ public class MusicDataStore { } catch (AlreadyExistsException ae) { - logger.error(EELFLoggerDelegate.errorLogger, "Executing Session Failure for Request = " - + "[" + queryObject.getQuery() + "]" + " Reason = " + ae.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, ae.getMessage(),AppMessages.SESSIONFAILED+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ae.getMessage()); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, "Executing Session Failure for Request = " - + "[" + queryObject.getQuery() + "]" + " Reason = " + e.getMessage()); - throw new MusicServiceException("Executing Session Failure for Request = " + "[" + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONFAILED+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Executing Session Failure for Request = " + "[" + queryObject.getQuery() + "]" + " Reason = " + e.getMessage()); } @@ -351,7 +369,8 @@ public class MusicDataStore { throws MusicServiceException, MusicQueryException { if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { - throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + queryObject.getQuery() + "]"); } logger.info(EELFLoggerDelegate.applicationLogger, @@ -363,8 +382,8 @@ public class MusicDataStore { results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); - throw new MusicServiceException(ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); } return results; } @@ -381,8 +400,8 @@ public class MusicDataStore { public ResultSet executeCriticalGet(PreparedQueryObject queryObject) throws MusicServiceException, MusicQueryException { if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) { - logger.error(EELFLoggerDelegate.errorLogger, "Error processing Prepared Query Object"); - throw new MusicQueryException("Ill formed queryObject for the request = " + "[" + logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "[" + queryObject.getQuery() + "]"); } logger.info(EELFLoggerDelegate.applicationLogger, @@ -393,8 +412,8 @@ public class MusicDataStore { try { results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray())); } catch (Exception ex) { - logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage()); - throw new MusicServiceException(ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + throw new MusicServiceException(ex.getMessage()); } return results; diff --git a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java index 22c0104b..b7a9ec23 100644 --- a/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java +++ b/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java @@ -35,7 +35,8 @@ public class JsonInsert implements Serializable { private String keyspaceName; private String tableName; private Map<String, Object> values; - String ttl, timestamp; + private String ttl; + private String timestamp; private Map<String, Object> row_specification; private Map<String, String> consistencyInfo; @@ -109,7 +110,6 @@ public class JsonInsert implements Serializable { out = new ObjectOutputStream(bos); out.writeObject(this); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } return bos.toByteArray(); diff --git a/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java b/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java new file mode 100644 index 00000000..f265eae3 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/format/AppMessages.java @@ -0,0 +1,177 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.eelf.logging.format; + +/** + * @author inam + * + */ +public enum AppMessages { + + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Zookeepr/Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Zookeeper error has occured + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Failed to get ZK Lock Handle + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + + + + MISSINGINFO("[ERR100E]", "Missing Information ","Details: NA", "Please check application credentials and headers"), + AUTHENTICATIONERROR("[ERR101E]", "Authentication error occured ","Details: NA", "Please verify application credentials"), + CONNCECTIVITYERROR("[ERR200E]"," Connectivity error","Details: NA ","Please check connectivity to external resources"), + HOSTUNAVAILABLE("[ERR201E]","Host not available","Details: NA","Please verify the host details"), + CASSANDRACONNECTIVITY("[ERR202E]","Error while connecting to Cassandra cluster",""," Please check cassandra cluster details"), + IOERROR("[ERR203E]","IO Error has occured","","Please check IO"), + EXECUTIONINTERRUPTED("[ERR204E]"," Execution Interrupted","",""), + SESSIONEXPIRED("[ERR205E]"," Session Expired","","Session has expired."), + CACHEAUTHENTICATION("[ERR206E]","Cache not authenticated",""," Cache not authenticated"), + + QUERYERROR("[ERR400E]","Error while processing prepared query object",""," Please verify the query"), + SESSIONFAILED("[ERR401E]","Executing Session Failure for Request","","Please verify the session and request"), + + INVALIDLOCK("[ERR500E]"," Invalid lock or acquire failed",""," Lock is not valid to aquire"), + LOCKINGERROR("[ERR501E]"," Locking Error has occured",""," Locking Error has occured"), + KEEPERERROR("[ERR502E]"," Zookeeper error has occured","","Please check zookeeper details"), + LOCKHANDLE("[ERR503E]","Failed to aquire lock store handle",""," Failed to aquire lock store handle"), + CREATELOCK("[ERR504E]","Failed to aquire lock store handle ","","Failed to aquire lock store handle "), + LOCKSTATE("[ERR508E]"," Lock state not set",""," Lock state not set"), + DESTROYLOCK("[ERR509E]"," Lock not destroyed",""," Lock not destroyed"), + RELEASELOCK("[ERR510E]"," Lock not released",""," Lock not released"), + DELTELOCK("[ERR511E]",""," Lock not deleted "," Lock not deleted "), + CACHEERROR("[ERR600E]"," Error initializing the cache",""," Error initializing the cache"), + + UNKNOWNERROR("[ERR900E]"," Unexpected error occured",""," Please check logs for details"); + + + + ErrorTypes eType; + ErrorSeverity alarmSeverity; + ErrorSeverity errorSeverity; + String errorCode; + String errorDescription; + String details; + String resolution; + + + AppMessages(String errorCode, String errorDescription, String details,String resolution) { + + this.errorCode = errorCode; + this.errorDescription = errorDescription; + this.details = details; + this.resolution = resolution; + } + + + + + AppMessages(ErrorTypes eType, ErrorSeverity alarmSeverity, + ErrorSeverity errorSeverity, String errorCode, String errorDescription, String details, + String resolution) { + + this.eType = eType; + this.alarmSeverity = alarmSeverity; + this.errorSeverity = errorSeverity; + this.errorCode = errorCode; + this.errorDescription = errorDescription; + this.details = details; + this.resolution = resolution; + } + + public String getDetails() { + return this.details; + } + + public String getResolution() { + return this.resolution; + } + + public String getErrorCode() { + return this.errorCode; + } + + public String getErrorDescription() { + return this.errorDescription; + } + + + + + + + +} diff --git a/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java b/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java new file mode 100644 index 00000000..b18c1771 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/format/ErrorCodes.java @@ -0,0 +1,106 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.eelf.logging.format; + + + +/** + * @author inam + * + */ +public enum ErrorCodes { + + + /* + * 100-199 Security/Permission Related - Authentication problems + * [ERR100E] Missing Information + * [ERR101E] Authentication error occured + * + * 200-299 Availability/Timeout Related/IO - connectivity error - connection timeout + * [ERR200E] Connectivity + * [ERR201E] Host not available + * [ERR202E] Error while connecting to Cassandra cluster + * [ERR203E] IO Error has occured + * [ERR204E] Execution Interrupted + * [ERR205E] Session Expired + * [ERR206E] Cache not authenticated + * + * + * 300-399 Data Access/Integrity Related + * + * 400-499 - Cassandra Query Related + * [ERR400E] Error while processing prepared query object + * [ERR401E] Executing Session Failure for Request + * [ERR402E] Ill formed queryObject for the request + * [ERR403E] Error processing Prepared Query Object + * + * 500-599 - Zookeepr/Locking Related + * [ERR500E] Invalid lock + * [ERR501E] Locking Error has occured + * [ERR502E] Zookeeper error has occured + * [ERR503E] Failed to aquire lock store handle + * [ERR504E] Failed to create Lock Reference + * [ERR505E] Lock does not exist + * [ERR506E] Failed to aquire lock + * [ERR507E] Lock not aquired + * [ERR508E] Lock state not set + * [ERR509E] Lock not destroyed + * [ERR510E] Lock not released + * [ERR511E] Lock not deleted + * [ERR512E] Failed to get ZK Lock Handle + * + * + * 600 - 699 - Music Service Errors + * [ERR600E] Error initializing the cache + * + * 700-799 Schema Interface Type/Validation - received Pay-load checksum is + * invalid - received JSON is not valid + * + * 800-899 Business/Flow Processing Related - check out to service is not + * allowed - Roll-back is done - failed to generate heat file + * + * + * 900-999 Unknown Errors - Unexpected exception + * [ERR900E] Unexpected error occured + * [ERR901E] Number format exception + * + * + * 1000-1099 Reserved - do not use + * + */ + + /*SUCCESS("Success"), FAILURE("Failure"); + + private String result; + + ResultType(String result) { + this.result = result; + } + + public String getResult() { + return result; + } +*/ + + + +} diff --git a/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java b/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java new file mode 100644 index 00000000..cda5dd31 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/format/ErrorSeverity.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.eelf.logging.format; + +/** + * @author inam + * + */ +public enum ErrorSeverity { + INFO, + WARN, + ERROR, + FATAL, + CRITICAL, + MAJOR, + MINOR, + NONE, +} diff --git a/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java b/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java new file mode 100644 index 00000000..2536f4a4 --- /dev/null +++ b/src/main/java/org/onap/music/eelf/logging/format/ErrorTypes.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.eelf.logging.format; + +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +/** + * @author inam + * + */ +public enum ErrorTypes implements EELFResolvableErrorEnum { + + + CONNECTIONERROR, + SESSIONEXPIRED, + AUTHENTICATIONERROR, + SERVICEUNAVAILABLE, + QUERYERROR, + DATAERROR, + GENERALSERVICEERROR, + MUSICSERVICEERROR, + LOCKINGERROR, + UNKNOWN, + +} diff --git a/src/main/java/org/onap/music/lockingservice/MusicLockState.java b/src/main/java/org/onap/music/lockingservice/MusicLockState.java index 10cdc0e7..5d051be4 100644 --- a/src/main/java/org/onap/music/lockingservice/MusicLockState.java +++ b/src/main/java/org/onap/music/lockingservice/MusicLockState.java @@ -30,6 +30,9 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; // the state variable that will be stored in zookeeper, capturing the transitions of public class MusicLockState implements Serializable { @@ -104,7 +107,7 @@ public class MusicLockState implements Serializable { out = new ObjectOutputStream(bos); out.writeObject(this); } catch (IOException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); } return bos.toByteArray(); } @@ -117,7 +120,7 @@ public class MusicLockState implements Serializable { in = new ObjectInputStream(bis); o = in.readObject(); } catch (ClassNotFoundException | IOException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.UNKNOWN); } return (MusicLockState) o; } diff --git a/src/main/java/org/onap/music/lockingservice/MusicLockingService.java b/src/main/java/org/onap/music/lockingservice/MusicLockingService.java index 9b21f596..2fc8a151 100644 --- a/src/main/java/org/onap/music/lockingservice/MusicLockingService.java +++ b/src/main/java/org/onap/music/lockingservice/MusicLockingService.java @@ -28,6 +28,9 @@ import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooKeeper; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.main.MusicUtil; @@ -35,7 +38,7 @@ import org.onap.music.main.MusicUtil; public class MusicLockingService implements Watcher { - + private static final int SESSION_TIMEOUT = 180000; ZkStatelessLockService zkLockHandle = null; private CountDownLatch connectedSignal = new CountDownLatch(1); @@ -48,10 +51,10 @@ public class MusicLockingService implements Watcher { connectedSignal.await(); zkLockHandle = new ZkStatelessLockService(zk); } catch (IOException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); throw new MusicServiceException("IO Error has occured" + e.getMessage()); } catch (InterruptedException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); throw new MusicServiceException("Exception Occured " + e.getMessage()); } } @@ -65,13 +68,17 @@ public class MusicLockingService implements Watcher { ZooKeeper zk = new ZooKeeper(lockServer, SESSION_TIMEOUT, this); connectedSignal.await(); zkLockHandle = new ZkStatelessLockService(zk); - } catch (IOException | InterruptedException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - } + } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.CONNECTIONERROR); + }catch( InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } } public void createLockaIfItDoesNotExist(String lockName) { - if (zkLockHandle.checkIfLockExists(lockName) == false) { + if (!zkLockHandle.checkIfLockExists(lockName)) { String lockHolder = null; MusicLockState ml = new MusicLockState(MusicLockState.LockStatus.UNLOCKED, lockHolder); byte[] data = ml.serialize(); @@ -90,12 +97,14 @@ public class MusicLockingService implements Watcher { try{ data = zkLockHandle.getNodeData(lockName); }catch (Exception ex){ - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } if(data !=null) return MusicLockState.deSerialize(data); - else - throw new MusicLockingException("Invalid lock or acquire failed"); + else { + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.INVALIDLOCK, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + throw new MusicLockingException("Invalid lock or acquire failed"); + } } public String createLockId(String lockName) { @@ -109,9 +118,13 @@ public class MusicLockingService implements Watcher { String lockName = "/" + st.nextToken("/"); try { return zkLockHandle.lock(lockName, lockId); - } catch (KeeperException | InterruptedException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - } + } catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.LOCKINGERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch( InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch(Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + } return false; } diff --git a/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java b/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java index df4d6ad6..4082b3b8 100644 --- a/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java +++ b/src/main/java/org/onap/music/lockingservice/ProtocolSupport.java @@ -21,8 +21,6 @@ */ package org.onap.music.lockingservice; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; @@ -30,6 +28,9 @@ import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Stat; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.lockingservice.ZooKeeperOperation; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -41,7 +42,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * */ class ProtocolSupport { - private EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(ProtocolSupport.class); + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ProtocolSupport.class); protected ZooKeeper zookeeper; private AtomicBoolean closed = new AtomicBoolean(false); @@ -49,10 +50,6 @@ class ProtocolSupport { private int retryCount = 10; private List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE; - // public ProtocolSupport(ZooKeeper zookeeper) { - // this.zookeeper = zookeeper; - // } - /** * Closes this strategy and releases any ZooKeeper resources; but keeps the ZooKeeper instance * open @@ -111,7 +108,9 @@ class ProtocolSupport { /** * Allow derived classes to perform some custom closing operations to release resources */ - protected void doClose() {} + protected void doClose() { + throw new UnsupportedOperationException(); + } /** @@ -129,14 +128,15 @@ class ProtocolSupport { try { return operation.execute(); } catch (KeeperException.SessionExpiredException e) { - LOG.debug("Session expired for: " + zookeeper + " so reconnecting due to: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.SESSIONEXPIRED+" for: " + zookeeper + " so reconnecting due to: " + e, ErrorSeverity.ERROR, ErrorTypes.SESSIONEXPIRED); throw e; } catch (KeeperException.ConnectionLossException e) { if (exception == null) { exception = e; } - LOG.debug("Attempt " + i + " failed with connection loss so " - + "attempting to reconnect: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.CONNCECTIVITYERROR, ErrorSeverity.ERROR, ErrorTypes.SESSIONEXPIRED); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Attempt " + i + " failed with connection loss so attempting to reconnect: " + e); + retryDelay(i); } } @@ -174,9 +174,9 @@ class ProtocolSupport { } }); } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger,"Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger,"Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } } @@ -199,7 +199,9 @@ class ProtocolSupport { try { Thread.sleep(attemptCount * retryDelay); } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger,"Failed to sleep: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Thread failed to sleep: " + e); + Thread.currentThread().interrupt(); } } } diff --git a/src/main/java/org/onap/music/lockingservice/ZNodeName.java b/src/main/java/org/onap/music/lockingservice/ZNodeName.java index eefc81a9..0c190f14 100644 --- a/src/main/java/org/onap/music/lockingservice/ZNodeName.java +++ b/src/main/java/org/onap/music/lockingservice/ZNodeName.java @@ -22,6 +22,8 @@ package org.onap.music.lockingservice; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; /** * Represents an ephemeral znode name which has an ordered sequence number and can be sorted in @@ -32,7 +34,7 @@ class ZNodeName implements Comparable<ZNodeName> { private final String name; private String prefix; private int sequence = -1; - private EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(ZNodeName.class); + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ZNodeName.class); public ZNodeName(String name) { if (name == null) { @@ -48,9 +50,9 @@ class ZNodeName implements Comparable<ZNodeName> { // If an exception occurred we misdetected a sequence suffix, // so return -1. } catch (NumberFormatException e) { - LOG.error(EELFLoggerDelegate.errorLogger,"Number format exception for " + idx, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Number format exception "+idx, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); } catch (ArrayIndexOutOfBoundsException e) { - LOG.error(EELFLoggerDelegate.errorLogger,"Array out of bounds for " + idx, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Array out of bounds for "+idx, ErrorSeverity.ERROR, ErrorTypes.GENERALSERVICEERROR); } } } diff --git a/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java b/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java index bd8ddfe3..51efafbf 100644 --- a/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java +++ b/src/main/java/org/onap/music/lockingservice/ZkStatelessLockService.java @@ -28,6 +28,9 @@ import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Stat; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; /** * A <a href="package.html">protocol to implement an exclusive write lock or to elect a leader</a>. @@ -44,7 +47,7 @@ public class ZkStatelessLockService extends ProtocolSupport { zookeeper = zk; } - private static EELFLoggerDelegate LOG = + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ZkStatelessLockService.class); protected void createLock(final String path, final byte[] data) { @@ -56,18 +59,18 @@ public class ZkStatelessLockService extends ProtocolSupport { return true; } }); - } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); - } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } } public void close() { try { zookeeper.close(); - } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } } @@ -80,10 +83,10 @@ public class ZkStatelessLockService extends ProtocolSupport { return true; } }); - } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); - } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } } @@ -95,8 +98,10 @@ public class ZkStatelessLockService extends ProtocolSupport { else return null; - } catch (KeeperException | InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } return null; } @@ -108,8 +113,10 @@ public class ZkStatelessLockService extends ProtocolSupport { if (stat != null) { result = true; } - } catch (KeeperException | InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } return result; } @@ -123,8 +130,10 @@ public class ZkStatelessLockService extends ProtocolSupport { LockZooKeeperOperation zop = new LockZooKeeperOperation(dir); try { retryOperation(zop); - } catch (KeeperException | InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + }catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); + }catch (KeeperException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); } return zop.getId(); } @@ -161,13 +170,13 @@ public class ZkStatelessLockService extends ProtocolSupport { }; zopdel.execute(); } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); // set that we have been interrupted. Thread.currentThread().interrupt(); } catch (KeeperException.NoNodeException e) { // do nothing } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); } } @@ -187,13 +196,13 @@ public class ZkStatelessLockService extends ProtocolSupport { } return sortedNames.first().getName(); } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); // set that we have been interrupted. Thread.currentThread().interrupt(); } catch (KeeperException.NoNodeException e) { // do nothing } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); } } @@ -216,13 +225,14 @@ public class ZkStatelessLockService extends ProtocolSupport { }; zopdel.execute(); } catch (InterruptedException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.EXECUTIONINTERRUPTED, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); // set that we have been interrupted. Thread.currentThread().interrupt(); } catch (KeeperException.NoNodeException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); // do nothing } catch (KeeperException e) { - LOG.error(EELFLoggerDelegate.errorLogger, "Caught: " + e, e); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.KEEPERERROR, ErrorSeverity.ERROR, ErrorTypes.LOCKINGERROR); throw (RuntimeException) new RuntimeException(e.getMessage()).initCause(e); } } @@ -272,8 +282,8 @@ public class ZkStatelessLockService extends ProtocolSupport { id = zookeeper.create(dir + "/" + prefix, data, getAcl(), CreateMode.PERSISTENT_SEQUENTIAL); - if (LOG.isDebugEnabled()) { - LOG.debug("Created id: " + id); + if (logger.isDebugEnabled()) { + logger.debug(EELFLoggerDelegate.debugLogger, "Created id: " + id); } if (id != null) break; @@ -281,10 +291,12 @@ public class ZkStatelessLockService extends ProtocolSupport { if (id != null) { List<String> names = zookeeper.getChildren(dir, false); if (names.isEmpty()) { - LOG.info(EELFLoggerDelegate.applicationLogger, "No children in: " + dir + logger.info(EELFLoggerDelegate.applicationLogger, "No children in: " + dir + " when we've just " + "created one! Lets recreate it..."); // lets force the recreation of the id id = null; + return Boolean.FALSE; + } else { // lets sort them explicitly (though they do seem to come back in order // ususally :) @@ -300,14 +312,14 @@ public class ZkStatelessLockService extends ProtocolSupport { if (!lessThanMe.isEmpty()) { ZNodeName lastChildName = lessThanMe.last(); String lastChildId = lastChildName.getName(); - if (LOG.isDebugEnabled()) { - LOG.debug("watching less than me node: " + lastChildId); + if (logger.isDebugEnabled()) { + logger.debug(EELFLoggerDelegate.debugLogger, "watching less than me node: " + lastChildId); } Stat stat = zookeeper.exists(lastChildId, false); if (stat != null) { return Boolean.FALSE; } else { - LOG.info(EELFLoggerDelegate.applicationLogger, + logger.info(EELFLoggerDelegate.applicationLogger, "Could not find the" + " stats for less than me: " + lastChildName.getName()); } diff --git a/src/main/java/org/onap/music/main/CachingUtil.java b/src/main/java/org/onap/music/main/CachingUtil.java index 4b2b4824..aee3abbf 100755 --- a/src/main/java/org/onap/music/main/CachingUtil.java +++ b/src/main/java/org/onap/music/main/CachingUtil.java @@ -36,6 +36,9 @@ import org.codehaus.jackson.map.ObjectMapper; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.AAFResponse; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicServiceException; import com.att.eelf.configuration.EELFLogger; @@ -83,8 +86,8 @@ public class CachingUtil implements Runnable { try { pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), false)); } catch (Exception e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(),AppMessages.CACHEERROR, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); e1.printStackTrace(); - logger.error(EELFLoggerDelegate.errorLogger,"Exception is "+ e1.getMessage() + "during initalizeAafCache"); } ResultSet rs = MusicCore.get(pQuery); Iterator<Row> it = rs.iterator(); @@ -109,11 +112,9 @@ public class CachingUtil implements Runnable { + nameSpace); } } catch (Exception e) { - // TODO Auto-generated catch block + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Something at AAF was changed for ns: " + nameSpace+" So not updating Cache for the namespace. "); e.printStackTrace(); - logger.error("Something at AAF was changed for ns: " + nameSpace - + ". So not updating Cache for the namespace. "); - logger.error("Exception is " + e.getMessage()); } } @@ -121,11 +122,11 @@ public class CachingUtil implements Runnable { @Override public void run() { - logger.debug("Scheduled task invoked. Refreshing Cache..."); + logger.info(EELFLoggerDelegate.applicationLogger,"Scheduled task invoked. Refreshing Cache..."); try { initializeAafCache(); } catch (MusicServiceException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); } } @@ -134,9 +135,9 @@ public class CachingUtil implements Runnable { if (aafCache.get(nameSpace) != null) { if (keySpace != null && !musicCache.get(nameSpace).equals(keySpace)) { - logger.debug("Create new application for the same namespace."); + logger.info(EELFLoggerDelegate.applicationLogger,"Create new application for the same namespace."); } else if (aafCache.get(nameSpace).get(userId).equals(password)) { - logger.debug("Authenticated with cache value.."); + logger.info(EELFLoggerDelegate.applicationLogger,"Authenticated with cache value.."); // reset invalid attempts to 0 userAttempts.put(nameSpace, 0); return true; @@ -154,10 +155,11 @@ public class CachingUtil implements Runnable { logger.info(EELFLoggerDelegate.applicationLogger,"Resetting failed attempt."); userAttempts.put(nameSpace, 0); } else { + logger.info(EELFLoggerDelegate.applicationLogger,"No more attempts allowed. Please wait for atleast 2 min."); throw new Exception("No more attempts allowed. Please wait for atleast 2 min."); } } - logger.error(EELFLoggerDelegate.errorLogger,"Cache not authenticated.."); + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.CACHEAUTHENTICATION,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); logger.info(EELFLoggerDelegate.applicationLogger,"Check AAF again..."); } } @@ -178,6 +180,7 @@ public class CachingUtil implements Runnable { private static AAFResponse triggerAAF(String nameSpace, String userId, String password) throws Exception { if (MusicUtil.getAafEndpointUrl() == null) { + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); throw new Exception("AAF endpoint is not set. Please specify in the properties file."); } Client client = Client.create(); @@ -213,6 +216,7 @@ public class CachingUtil implements Runnable { response.bufferEntity(); String x = response.getEntity(String.class); AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class); + return responseObj; } @@ -235,7 +239,7 @@ public class CachingUtil implements Runnable { musicCache.put(keyspace, uuid); } catch (Exception e) { String msg = e.getMessage(); - logger.error("Exception occured during uuid retrieval from DB." + e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); resultMap.put("Exception", "Unauthorized operation. Check AID and Keyspace. " + "Exception from MUSIC is: " + (msg == null ? "Keyspace is new so no AID should be passed in Header." @@ -273,8 +277,8 @@ public class CachingUtil implements Runnable { uuid = rs.getUUID("uuid").toString(); musicLockCache.put(nameSpace, uuid); } catch (Exception e) { - logger.error("Exception occured during uuid retrieval from DB." + e.getMessage()); - resultMap.put("Exception", "Unauthorized operation. Check AID and Namespace. "); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + resultMap.put("Exception", "Unauthorized operation. Check AID and Namespace. "); return resultMap; } if (!musicLockCache.get(nameSpace).toString().equals(aid)) { @@ -295,7 +299,7 @@ public class CachingUtil implements Runnable { public static void updateMusicCache(String aid, String keyspace) { - logger.info("Updating musicCache for keyspace " + keyspace + " with aid " + aid); + logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for keyspace " + keyspace + " with aid " + aid); musicCache.put(keyspace, aid); } @@ -316,12 +320,11 @@ public class CachingUtil implements Runnable { isAAF = String.valueOf(rs.getBool("is_aaf")); appNameCache.put(namespace, isAAF); } catch (Exception e) { - logger.error("Exception occured during uuid retrieval from DB." + e.getMessage()); - e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + e.printStackTrace(); } } - return Boolean.valueOf(isAAF); } @@ -354,7 +357,7 @@ public class CachingUtil implements Runnable { try { appName = rs.getString("application_name"); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,"Exception occured during uuid retrieval from DB."+e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); e.printStackTrace(); } return appName; @@ -378,31 +381,49 @@ public class CachingUtil implements Runnable { } - public static Map<String, Object> verifyOnboarding(String ns, String userId, String password) - throws Exception { + public static Map<String, Object> verifyOnboarding(String ns, String userId, String password) { Map<String, Object> resultMap = new HashMap<>(); if (ns == null || userId == null || password == null) { - logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: "+userId+" :: password: "+password); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: "+userId+" :: password: "+password); resultMap.put("Exception", "One or more required headers appName(ns), userId, password is missing. Please check."); return resultMap; } PreparedQueryObject queryObject = new PreparedQueryObject(); queryObject.appendQueryString( - "select * from admin.keyspace_master where application_name = ? and username = ? and password = ? allow filtering"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); - Row rs = MusicCore.get(queryObject).one(); + "select * from admin.keyspace_master where application_name = ? allow filtering"); + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); + } catch(Exception e) { + resultMap.put("Exception", + "Unable to process input data. Invalid input data type. Please check ns, userId and password values. "+e.getMessage()); + return resultMap; + } + Row rs = null; + try { + rs = MusicCore.get(queryObject).one(); + } catch (MusicServiceException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + resultMap.put("Exception", "Unable to process operation. Error is "+e.getMessage()); + return resultMap; + } if (rs == null) { - logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); - - resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + logger.error(EELFLoggerDelegate.errorLogger,"Application is not onboarded. Please contact admin."); + resultMap.put("Exception", "Application is not onboarded. Please contact admin."); } else { + if(!(rs.getString("username").equals(userId)) && !(rs.getString("password").equals("password"))) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + return resultMap; + } boolean is_aaf = rs.getBool("is_aaf"); String keyspace = rs.getString("keyspace_name"); if (!is_aaf) { if (!keyspace.equals(MusicUtil.DEFAULTKEYSPACENAME)) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); logger.error(EELFLoggerDelegate.errorLogger,"Non AAF applications are allowed to have only one keyspace per application."); resultMap.put("Exception", "Non AAF applications are allowed to have only one keyspace per application."); diff --git a/src/main/java/org/onap/music/main/MusicCore.java b/src/main/java/org/onap/music/main/MusicCore.java index 3d5cf4e5..73a6ee55 100644 --- a/src/main/java/org/onap/music/main/MusicCore.java +++ b/src/main/java/org/onap/music/main/MusicCore.java @@ -31,7 +31,9 @@ import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonKeySpace; import org.onap.music.eelf.logging.EELFLoggerDelegate; -// import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicLockingException; import org.onap.music.exceptions.MusicQueryException; import org.onap.music.exceptions.MusicServiceException; @@ -66,7 +68,7 @@ public class MusicCore { this.selectQueryForTheRow = selectQueryForTheRow; } - public boolean testCondition() { + public boolean testCondition() throws Exception { // first generate the row ResultSet results = quorumGet(selectQueryForTheRow); Row row = results.one(); @@ -83,7 +85,7 @@ public class MusicCore { try { mLockHandle = new MusicLockingService(); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to aquire Locl store handle" + e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKHANDLE,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); throw new MusicLockingException("Failed to aquire Locl store handle " + e); } } @@ -111,12 +113,24 @@ public class MusicCore { /** * * @return + * @throws MusicServiceException */ - public static MusicDataStore getDSHandle() { + public static MusicDataStore getDSHandle() throws MusicServiceException { logger.info(EELFLoggerDelegate.applicationLogger,"Acquiring data store handle"); long start = System.currentTimeMillis(); if (mDstoreHandle == null) { - mDstoreHandle = new MusicDataStore(); + // Quick Fix - Best to put this into every call to getDSHandle? + if (! MusicUtil.getMyCassaHost().equals("localhost") ) { + mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost()); + } else { + mDstoreHandle = new MusicDataStore(); + } + } + if(mDstoreHandle.getSession() == null) { + String message = "Connection to Cassandra has not been enstablished." + + " Please check connection properites and reboot."; + logger.info(EELFLoggerDelegate.applicationLogger, message); + throw new MusicServiceException(message); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to acquire data store handle:" + (end - start) + " ms"); @@ -130,7 +144,8 @@ public class MusicCore { try { lockId = getLockingServiceHandle().createLockId("/" + lockName); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to create Lock Reference " + lockName); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.CREATELOCK+lockName,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to create lock reference:" + (end - start) + " ms"); @@ -169,7 +184,7 @@ public class MusicCore { logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to get lock state:" + (end - start) + " ms"); return mls; } catch (NullPointerException | MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"No lock object exists as of now.." + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } return null; } @@ -194,14 +209,18 @@ public class MusicCore { } } } else - logger.debug("There is no lock state object for " + key); - + logger.error(EELFLoggerDelegate.errorLogger,key, AppMessages.INVALIDLOCK,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + /* * call the traditional acquire lock now and if the result returned is true, set the * begin time-stamp and lease period */ if (acquireLock(key, lockId).getResult() == ResultType.SUCCESS) { mls = getMusicLockState(key);// get latest state + if ( mls == null ) { + logger.info(EELFLoggerDelegate.applicationLogger,"Music Lock State is null"); + return new ReturnType(ResultType.FAILURE, "Could not acquire lock, Lock State is null"); + } if (mls.getLeaseStartTime() == -1) {// set it again only if it is not set already mls.setLeaseStartTime(System.currentTimeMillis()); mls.setLeasePeriod(leasePeriod); @@ -217,7 +236,8 @@ public class MusicCore { } } catch (Exception e) { StringWriter sw = new StringWriter(); - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR506E] Failed to aquire lock ",ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); + String exceptionAsString = sw.toString(); return new ReturnType(ResultType.FAILURE, "Exception thrown in acquireLockWithLease:\n" + exceptionAsString); @@ -234,9 +254,9 @@ public class MusicCore { try { result = getLockingServiceHandle().isMyTurn(lockId); } catch (MusicLockingException e2) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to aquireLock lockId " + lockId + " " + e2); + logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId + " " + e2); } - if (result == false) { + if (!result) { logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Not your turn, someone else has the lock"); try { if (!getLockingServiceHandle().lockIdExists(lockId)) { @@ -244,7 +264,7 @@ public class MusicCore { return new ReturnType(ResultType.FAILURE, "Lockid doesn't exist"); } } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to check if lockid exists - lockId " + lockId + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: returning failure"); return new ReturnType(ResultType.FAILURE, "Not your turn, someone else has the lock"); @@ -253,7 +273,7 @@ public class MusicCore { // this is for backward compatibility where locks could also be acquired on just // keyspaces or tables. - if (isTableOrKeySpaceLock(key) == true) { + if (isTableOrKeySpaceLock(key)) { logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: A table or keyspace lock so no need to perform sync...so returning true"); return new ReturnType(ResultType.SUCCESS, "A table or keyspace lock so no need to perform sync...so returning true"); } @@ -270,7 +290,7 @@ public class MusicCore { return new ReturnType(ResultType.SUCCESS, "You already have the lock!"); } } catch (NullPointerException e) { - logger.error(EELFLoggerDelegate.errorLogger,"In acquire lock:No one has tried to acquire the lock yet.."); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.INVALIDLOCK+lockId,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } // change status to "being locked". This state transition is necessary to ensure syncing @@ -286,14 +306,18 @@ public class MusicCore { try { getLockingServiceHandle().setLockState(key, newMls); } catch (MusicLockingException e1) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + key + " " + e1); + logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to being_locked"); // do syncing if this was a forced lock release if (needToSyncQuorum) { logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Since there was a forcible release, need to sync quorum!"); - syncQuorum(key); + try { + syncQuorum(key); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + e); + } } // change status to locked @@ -303,7 +327,7 @@ public class MusicCore { try { getLockingServiceHandle().setLockState(key, newMls); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to set Lock state " + key + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKSTATE+key,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } logger.info(EELFLoggerDelegate.applicationLogger,"In acquire lock: Set lock state to locked and assigned current lock ref " + lockId + " as holder"); @@ -325,7 +349,7 @@ public class MusicCore { } - private static void syncQuorum(String key) { + private static void syncQuorum(String key) throws Exception { logger.info(EELFLoggerDelegate.applicationLogger,"Performing sync operation---"); String[] splitString = key.split("\\."); String keyspaceName = splitString[0]; @@ -346,8 +370,6 @@ public class MusicCore { selectQuery.appendQueryString("SELECT * FROM " + keyspaceName + "." + tableName + " WHERE " + primaryKeyName + "= ?" + ";"); selectQuery.addValue(cqlFormattedPrimaryKeyValue); - // String selectQuery = "SELECT * FROM "+keyspaceName+"."+tableName+ " WHERE - // "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";"; ResultSet results = null; try { results = getDSHandle().executeCriticalGet(selectQuery); @@ -356,7 +378,6 @@ public class MusicCore { ColumnDefinitions colInfo = row.getColumnDefinitions(); int totalColumns = colInfo.size(); int counter = 1; - // String fieldValueString=""; StringBuilder fieldValueString = new StringBuilder(""); for (Definition definition : colInfo) { String colName = definition.getName(); @@ -365,7 +386,6 @@ public class MusicCore { DataType colType = definition.getType(); Object valueObj = getDSHandle().getColValue(row, colName, colType); Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); - // fieldValueString = fieldValueString+ colName+"="+valueString; fieldValueString.append(colName + " = ?"); updateQuery.addValue(valueString); if (counter != (totalColumns - 1)) @@ -375,12 +395,10 @@ public class MusicCore { updateQuery.appendQueryString("UPDATE " + keyspaceName + "." + tableName + " SET " + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";"); updateQuery.addValue(cqlFormattedPrimaryKeyValue); - // String updateQuery = "UPDATE "+keyspaceName+"."+tableName+" SET "+fieldValueString+" - // WHERE "+primaryKeyName+"="+cqlFormattedPrimaryKeyValue+";"; getDSHandle().executePut(updateQuery, "critical"); } catch (MusicServiceException | MusicQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to execute update query " + updateQuery + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR); } } @@ -397,7 +415,8 @@ public class MusicCore { try { results = getDSHandle().executeCriticalGet(query); } catch (MusicServiceException | MusicQueryException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.MAJOR, ErrorTypes.GENERALSERVICEERROR); + } return results; @@ -407,8 +426,9 @@ public class MusicCore { * * @param results * @return + * @throws MusicServiceException */ - public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) { + public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException { return getDSHandle().marshalData(results); } @@ -422,7 +442,7 @@ public class MusicCore { try { return getLockingServiceHandle().whoseTurnIsIt("/" + lockName) + ""; } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed whoseTurnIsIt " + lockName + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.LOCKINGERROR+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } return null; @@ -444,7 +464,7 @@ public class MusicCore { try { getLockingServiceHandle().unlockAndDeleteId(lockId); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to Destroy Lock Ref " + lockId + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DESTROYLOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to destroy lock reference:" + (end - start) + " ms"); @@ -455,7 +475,7 @@ public class MusicCore { try { getLockingServiceHandle().unlockAndDeleteId(lockId); } catch (MusicLockingException e1) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockId + " " + e1); + logger.error(EELFLoggerDelegate.errorLogger,e1.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } String lockName = getLockNameFromId(lockId); MusicLockState mls; @@ -472,7 +492,7 @@ public class MusicCore { try { getLockingServiceHandle().setLockState(lockName, mls); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to release Lock " + lockName + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.RELEASELOCK+lockId ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to release lock:" + (end - start) + " ms"); @@ -493,7 +513,7 @@ public class MusicCore { try { getLockingServiceHandle().deleteLock("/" + lockName); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to Delete Lock " + lockName + " " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.DELTELOCK+lockName ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken to delete lock:" + (end - start) + " ms"); @@ -506,8 +526,9 @@ public class MusicCore { * @param keyspace * @param tablename * @return + * @throws MusicServiceException */ - public static TableMetadata returnColumnMetadata(String keyspace, String tablename) { + public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException { return getDSHandle().returnColumnMetadata(keyspace, tablename); } @@ -520,7 +541,7 @@ public class MusicCore { try { getLockingServiceHandle().getzkLockHandle().createNode(nodeName); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } } @@ -535,7 +556,7 @@ public class MusicCore { try { getLockingServiceHandle().getzkLockHandle().setNodeData(nodeName, data); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } logger.info(EELFLoggerDelegate.applicationLogger,"Performed zookeeper write to " + nodeName); long end = System.currentTimeMillis(); @@ -553,7 +574,7 @@ public class MusicCore { try { data = getLockingServiceHandle().getzkLockHandle().getNodeData(nodeName); } catch (MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,"Failed to get ZK Lock Handle " + e); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR); } long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the actual zk put:" + (end - start) + " ms"); @@ -578,6 +599,7 @@ public class MusicCore { try { result = getDSHandle().executePut(queryObject, MusicUtil.EVENTUAL); } catch (MusicServiceException | MusicQueryException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), "[ERR512E] Failed to get ZK Lock Handle " ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() + " " + ex.getCause() + " " + ex); } if (result) { @@ -604,10 +626,16 @@ public class MusicCore { MusicLockState mls = getLockingServiceHandle() .getLockState(keyspaceName + "." + tableName + "." + primaryKey); if (mls.getLockHolder().equals(lockId) == true) { - if (conditionInfo != null)// check if condition is true + if (conditionInfo != null) + try { if (conditionInfo.testCondition() == false) return new ReturnType(ResultType.FAILURE, "Lock acquired but the condition is not true"); + } catch (Exception e) { + return new ReturnType(ResultType.FAILURE, + "Exception thrown while doing the critical put, check sanctity of the row/conditions:\n" + + e.getMessage()); + } getDSHandle().executePut(queryObject, MusicUtil.CRITICAL); long end = System.currentTimeMillis(); logger.info(EELFLoggerDelegate.applicationLogger,"Time taken for the critical put:" + (end - start) + " ms"); @@ -642,7 +670,7 @@ public class MusicCore { try { result = getDSHandle().executePut(queryObject, consistency); } catch (MusicQueryException | MusicServiceException ex) { - logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); throw new MusicServiceException(ex.getMessage()); } return result; @@ -688,7 +716,7 @@ public class MusicCore { } else throw new MusicServiceException("YOU DO NOT HAVE THE LOCK"); } catch (MusicQueryException | MusicServiceException | MusicLockingException e) { - logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); } return results; } @@ -866,6 +894,7 @@ public class MusicCore { return resultMap; } if (aid == null && (userId == null || password == null)) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.DATAERROR); logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId + " :: password: " + password); resultMap.put("Exception", @@ -878,11 +907,12 @@ public class MusicCore { try { isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace); } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace); resultMap.put("Exception", e.getMessage()); } if (!isValid) { - logger.error(EELFLoggerDelegate.errorLogger,"User not authenticated with AAF."); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); resultMap.put("Exception", "User not authenticated..."); } if (!resultMap.isEmpty()) @@ -921,7 +951,7 @@ public class MusicCore { pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); - CachingUtil.updateMusicCache(uuid, keyspace); + //CachingUtil.updateMusicCache(uuid, keyspace); MusicCore.eventualPut(pQuery); resultMap.put("aid", uuid); } diff --git a/src/main/java/org/onap/music/main/MusicUtil.java b/src/main/java/org/onap/music/main/MusicUtil.java index a31e33f9..0f77614e 100755 --- a/src/main/java/org/onap/music/main/MusicUtil.java +++ b/src/main/java/org/onap/music/main/MusicUtil.java @@ -45,436 +45,444 @@ import com.datastax.driver.core.DataType; * */ public class MusicUtil { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); - - private static int myId = 0; - private static ArrayList<String> allIds = new ArrayList<String>(); - private static String publicIp = ""; - private static ArrayList<String> allPublicIps = new ArrayList<String>(); - private static String myZkHost = "localhost"; - private static String myCassaHost = "localhost"; - private static String defaultMusicIp = "localhost"; - private static boolean debug = true; - private static String version = "2.3.0"; - private static String musicRestIp = "localhost"; - private static String musicPropertiesFilePath = "/opt/app/music/etc/music.properties"; - private static long defaultLockLeasePeriod = 6000; - private static final String[] propKeys = new String[] { "zookeeper.host", "cassandra.host", "music.ip", "debug", - "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", "public.ip", - "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url" }; - - public static final String ATOMIC = "atomic"; - public static final String EVENTUAL = "eventual"; - public static final String CRITICAL = "critical"; - public static final String ATOMICDELETELOCK = "atomic_delete_lock"; - - public static final String DEFAULTKEYSPACENAME = "TBD"; - private static String cassName = "cassandra"; - private static String cassPwd; - private static String aafEndpointUrl = null; - - /** - * @return the cassName - */ - public static String getCassName() { - return cassName; - } - - /** - * @return the cassPwd - */ - public static String getCassPwd() { - return cassPwd; - } - - /** - * @return the aafEndpointUrl - */ - public static String getAafEndpointUrl() { - return aafEndpointUrl; - } - - /** - * - * @param aafEndpointUrl - */ - public static void setAafEndpointUrl(String aafEndpointUrl) { - MusicUtil.aafEndpointUrl = aafEndpointUrl; - } - - /** - * - * @return - */ - public static int getMyId() { - return myId; - } - - /** - * - * @param myId - */ - public static void setMyId(int myId) { - MusicUtil.myId = myId; - } - - /** - * - * @return - */ - public static ArrayList<String> getAllIds() { - return allIds; - } - - /** - * - * @param allIds - */ - public static void setAllIds(List<String> allIds) { - MusicUtil.allIds = (ArrayList<String>) allIds; - } - - /** - * - * @return - */ - public static String getPublicIp() { - return publicIp; - } - - /** - * - * @param publicIp - */ - public static void setPublicIp(String publicIp) { - MusicUtil.publicIp = publicIp; - } - - /** - * - * @return - */ - public static ArrayList<String> getAllPublicIps() { - return allPublicIps; - } - - /** - * - * @param allPublicIps - */ - public static void setAllPublicIps(List<String> allPublicIps) { - MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps; - } - - /** - * Returns An array of property names that should be in the Properties - * files. - * - * @return - */ - public static String[] getPropkeys() { - return propKeys; - } - - /** - * Get MusicRestIp - default = localhost property file value - music.rest.ip - * - * @return - */ - public static String getMusicRestIp() { - return musicRestIp; - } - - /** - * Set MusicRestIp - * - * @param musicRestIp - */ - public static void setMusicRestIp(String musicRestIp) { - MusicUtil.musicRestIp = musicRestIp; - } - - /** - * Get MusicPropertiesFilePath - Default = /opt/music/music.properties - * property file value - music.properties - * - * @return - */ - public static String getMusicPropertiesFilePath() { - return musicPropertiesFilePath; - } - - /** - * Set MusicPropertiesFilePath - * - * @param musicPropertiesFilePath - */ - public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) { - MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath; - } - - /** - * Get DefaultLockLeasePeriod - Default = 6000 property file value - - * lock.lease.period - * - * @return - */ - public static long getDefaultLockLeasePeriod() { - return defaultLockLeasePeriod; - } - - /** - * Set DefaultLockLeasePeriod - * - * @param defaultLockLeasePeriod - */ - public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) { - MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod; - } - - /** - * Set Debug - * - * @param debug - */ - public static void setDebug(boolean debug) { - MusicUtil.debug = debug; - } - - /** - * Is Debug - Default = true property file value - debug - * - * @return - */ - public static boolean isDebug() { - return debug; - } - - /** - * Set Version - * - * @param version - */ - public static void setVersion(String version) { - MusicUtil.version = version; - } - - /** - * Return the version property file value - version - * - * @return - */ - public static String getVersion() { - return version; - } - - /** - * Get MyZkHost - Zookeeper Hostname - Default = localhost property file - * value - zookeeper.host - * - * @return - */ - public static String getMyZkHost() { - return myZkHost; - } - - /** - * Set MyZkHost - Zookeeper Hostname - * - * @param myZkHost - */ - public static void setMyZkHost(String myZkHost) { - MusicUtil.myZkHost = myZkHost; - } - - /** - * Get MyCassHost - Cassandra Hostname - Default = localhost property file - * value - cassandra.host - * - * @return - */ - public static String getMyCassaHost() { - return myCassaHost; - } - - /** - * Set MyCassHost - Cassandra Hostname - * - * @param myCassaHost - */ - public static void setMyCassaHost(String myCassaHost) { - MusicUtil.myCassaHost = myCassaHost; - } - - /** - * Get DefaultMusicIp - Default = localhost property file value - music.ip - * - * @return - */ - public static String getDefaultMusicIp() { - return defaultMusicIp; - } - - /** - * Set DefaultMusicIp - * - * @param defaultMusicIp - */ - public static void setDefaultMusicIp(String defaultMusicIp) { - MusicUtil.defaultMusicIp = defaultMusicIp; - } - - /** - * - * @return - */ - public static String getTestType() { - String testType = ""; - try { - Scanner fileScanner = new Scanner(new File("")); - testType = fileScanner.next();// ignore the my id line - String batchSize = fileScanner.next();// ignore the my public ip - // line - fileScanner.close(); - } catch (FileNotFoundException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - } - return testType; - - } - - /** - * - * @param time - */ - public static void sleep(long time) { - try { - Thread.sleep(time); - } catch (InterruptedException e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); - } - } - - /** - * Utility function to check if the query object is valid. - * - * @param withparams - * @param queryObject - * @return - */ - public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) { - if (withparams) { - int noOfValues = queryObject.getValues().size(); - int noOfParams = 0; - char[] temp = queryObject.getQuery().toCharArray(); - for (int i = 0; i < temp.length; i++) { - if (temp[i] == '?') - noOfParams++; - } - return (noOfValues == noOfParams); - } else { - return !queryObject.getQuery().isEmpty(); - } - - } - - public static void setCassName(String cassName) { - MusicUtil.cassName = cassName; - } - - public static void setCassPwd(String cassPwd) { - MusicUtil.cassPwd = cassPwd; - } - - public static String convertToCQLDataType(DataType type, Object valueObj) { - - String value = ""; - switch (type.getName()) { - case UUID: - value = valueObj + ""; - break; - case TEXT: - case VARCHAR: - String valueString = valueObj + ""; - valueString = valueString.replace("'", "''"); - value = "'" + valueString + "'"; - break; - case MAP: { - Map<String, Object> otMap = (Map<String, Object>) valueObj; - value = "{" + jsonMaptoSqlString(otMap, ",") + "}"; - break; - } - default: - value = valueObj + ""; - break; - } - return value; - } - - /** - * - * @param colType - * @param valueObj - * @return - * @throws Exception - */ - public static Object convertToActualDataType(DataType colType, Object valueObj) { - String valueObjString = valueObj + ""; - switch (colType.getName()) { - case UUID: - return UUID.fromString(valueObjString); - case VARINT: - return BigInteger.valueOf(Long.parseLong(valueObjString)); - case BIGINT: - return Long.parseLong(valueObjString); - case INT: - return Integer.parseInt(valueObjString); - case FLOAT: - return Float.parseFloat(valueObjString); - case DOUBLE: - return Double.parseDouble(valueObjString); - case BOOLEAN: - return Boolean.parseBoolean(valueObjString); - case MAP: - return (Map<String, Object>) valueObj; - default: - return valueObjString; - } - } - - /** - * - * Utility function to parse json map into sql like string - * - * @param jMap - * @param lineDelimiter - * @return - */ - - public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) { - StringBuilder sqlString = new StringBuilder(); - int counter = 0; - for (Map.Entry<String, Object> entry : jMap.entrySet()) { - Object ot = entry.getValue(); - String value = ot + ""; - if (ot instanceof String) { - value = "'" + value.replace("'", "''") + "'"; - } - sqlString.append("'" + entry.getKey() + "':" + value); - if (counter != jMap.size() - 1) - sqlString.append(lineDelimiter); - counter = counter + 1; - } - return sqlString.toString(); - } - - public static Map<String, HashMap<String, Object>> setErrorResponse(MusicServiceException ex) { - Map<String, HashMap<String, Object>> results = new HashMap<>(); - HashMap<String, Object> tempMap = new HashMap<>(); - Map<String, Object> result = new HashMap<>(); - result.put("error-description", ex.getMessage()); - tempMap.put("error", result); - results.put("result", tempMap); - return results; - } + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class); + + public static final String ATOMIC = "atomic"; + public static final String EVENTUAL = "eventual"; + public static final String CRITICAL = "critical"; + public static final String ATOMICDELETELOCK = "atomic_delete_lock"; + + public static final String DEFAULTKEYSPACENAME = "TBD"; + + + private static int myId = 0; + private static ArrayList<String> allIds = new ArrayList<>(); + private static String publicIp = ""; + private static ArrayList<String> allPublicIps = new ArrayList<>(); + private static String myZkHost = "localhost"; + private static String myCassaHost = "localhost"; + private static String defaultMusicIp = "localhost"; + private static boolean debug = true; + private static String version = "2.3.0"; + private static String musicRestIp = "localhost"; + private static String musicPropertiesFilePath = "/opt/app/music/etc/music.properties"; + private static long defaultLockLeasePeriod = 6000; + private static final String[] propKeys = new String[] { "zookeeper.host", "cassandra.host", "music.ip", "debug", + "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", "public.ip", + "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url" }; + + private static String cassName = "cassandra"; + private static String cassPwd; + private static String aafEndpointUrl = null; + + private MusicUtil() { + throw new IllegalStateException("Utility Class"); + } + + + /** + * @return the cassName + */ + public static String getCassName() { + return cassName; + } + + /** + * @return the cassPwd + */ + public static String getCassPwd() { + return cassPwd; + } + + /** + * @return the aafEndpointUrl + */ + public static String getAafEndpointUrl() { + return aafEndpointUrl; + } + + /** + * + * @param aafEndpointUrl + */ + public static void setAafEndpointUrl(String aafEndpointUrl) { + MusicUtil.aafEndpointUrl = aafEndpointUrl; + } + + /** + * + * @return + */ + public static int getMyId() { + return myId; + } + + /** + * + * @param myId + */ + public static void setMyId(int myId) { + MusicUtil.myId = myId; + } + + /** + * + * @return + */ + public static List<String> getAllIds() { + return allIds; + } + + /** + * + * @param allIds + */ + public static void setAllIds(List<String> allIds) { + MusicUtil.allIds = (ArrayList<String>) allIds; + } + + /** + * + * @return + */ + public static String getPublicIp() { + return publicIp; + } + + /** + * + * @param publicIp + */ + public static void setPublicIp(String publicIp) { + MusicUtil.publicIp = publicIp; + } + + /** + * + * @return + */ + public static List<String> getAllPublicIps() { + return allPublicIps; + } + + /** + * + * @param allPublicIps + */ + public static void setAllPublicIps(List<String> allPublicIps) { + MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps; + } + + /** + * Returns An array of property names that should be in the Properties + * files. + * + * @return + */ + public static String[] getPropkeys() { + return propKeys; + } + + /** + * Get MusicRestIp - default = localhost property file value - music.rest.ip + * + * @return + */ + public static String getMusicRestIp() { + return musicRestIp; + } + + /** + * Set MusicRestIp + * + * @param musicRestIp + */ + public static void setMusicRestIp(String musicRestIp) { + MusicUtil.musicRestIp = musicRestIp; + } + + /** + * Get MusicPropertiesFilePath - Default = /opt/music/music.properties + * property file value - music.properties + * + * @return + */ + public static String getMusicPropertiesFilePath() { + return musicPropertiesFilePath; + } + + /** + * Set MusicPropertiesFilePath + * + * @param musicPropertiesFilePath + */ + public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) { + MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath; + } + + /** + * Get DefaultLockLeasePeriod - Default = 6000 property file value - + * lock.lease.period + * + * @return + */ + public static long getDefaultLockLeasePeriod() { + return defaultLockLeasePeriod; + } + + /** + * Set DefaultLockLeasePeriod + * + * @param defaultLockLeasePeriod + */ + public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) { + MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod; + } + + /** + * Set Debug + * + * @param debug + */ + public static void setDebug(boolean debug) { + MusicUtil.debug = debug; + } + + /** + * Is Debug - Default = true property file value - debug + * + * @return + */ + public static boolean isDebug() { + return debug; + } + + /** + * Set Version + * + * @param version + */ + public static void setVersion(String version) { + MusicUtil.version = version; + } + + /** + * Return the version property file value - version + * + * @return + */ + public static String getVersion() { + return version; + } + + /** + * Get MyZkHost - Zookeeper Hostname - Default = localhost property file + * value - zookeeper.host + * + * @return + */ + public static String getMyZkHost() { + return myZkHost; + } + + /** + * Set MyZkHost - Zookeeper Hostname + * + * @param myZkHost + */ + public static void setMyZkHost(String myZkHost) { + MusicUtil.myZkHost = myZkHost; + } + + /** + * Get MyCassHost - Cassandra Hostname - Default = localhost property file + * value - cassandra.host + * + * @return + */ + public static String getMyCassaHost() { + return myCassaHost; + } + + /** + * Set MyCassHost - Cassandra Hostname + * + * @param myCassaHost + */ + public static void setMyCassaHost(String myCassaHost) { + MusicUtil.myCassaHost = myCassaHost; + } + + /** + * Get DefaultMusicIp - Default = localhost property file value - music.ip + * + * @return + */ + public static String getDefaultMusicIp() { + return defaultMusicIp; + } + + /** + * Set DefaultMusicIp + * + * @param defaultMusicIp + */ + public static void setDefaultMusicIp(String defaultMusicIp) { + MusicUtil.defaultMusicIp = defaultMusicIp; + } + + /** + * + * @return + */ + public static String getTestType() { + String testType = ""; + try { + Scanner fileScanner = new Scanner(new File("")); + testType = fileScanner.next();// ignore the my id line + String batchSize = fileScanner.next();// ignore the my public ip + // line + fileScanner.close(); + } catch (FileNotFoundException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } + return testType; + + } + + /** + * + * @param time + */ + public static void sleep(long time) { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + Thread.currentThread().interrupt(); + } + } + + /** + * Utility function to check if the query object is valid. + * + * @param withparams + * @param queryObject + * @return + */ + public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) { + if (withparams) { + int noOfValues = queryObject.getValues().size(); + int noOfParams = 0; + char[] temp = queryObject.getQuery().toCharArray(); + for (int i = 0; i < temp.length; i++) { + if (temp[i] == '?') + noOfParams++; + } + return (noOfValues == noOfParams); + } else { + return !queryObject.getQuery().isEmpty(); + } + + } + + public static void setCassName(String cassName) { + MusicUtil.cassName = cassName; + } + + public static void setCassPwd(String cassPwd) { + MusicUtil.cassPwd = cassPwd; + } + + public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception { + + String value = ""; + switch (type.getName()) { + case UUID: + value = valueObj + ""; + break; + case TEXT: + case VARCHAR: + String valueString = valueObj + ""; + valueString = valueString.replace("'", "''"); + value = "'" + valueString + "'"; + break; + case MAP: { + Map<String, Object> otMap = (Map<String, Object>) valueObj; + value = "{" + jsonMaptoSqlString(otMap, ",") + "}"; + break; + } + default: + value = valueObj + ""; + break; + } + return value; + } + + /** + * + * @param colType + * @param valueObj + * @return + * @throws Exception + */ + public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception{ + String valueObjString = valueObj + ""; + switch (colType.getName()) { + case UUID: + return UUID.fromString(valueObjString); + case VARINT: + return BigInteger.valueOf(Long.parseLong(valueObjString)); + case BIGINT: + return Long.parseLong(valueObjString); + case INT: + return Integer.parseInt(valueObjString); + case FLOAT: + return Float.parseFloat(valueObjString); + case DOUBLE: + return Double.parseDouble(valueObjString); + case BOOLEAN: + return Boolean.parseBoolean(valueObjString); + case MAP: + return (Map<String, Object>) valueObj; + default: + return valueObjString; + } + } + + /** + * + * Utility function to parse json map into sql like string + * + * @param jMap + * @param lineDelimiter + * @return + */ + + public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{ + StringBuilder sqlString = new StringBuilder(); + int counter = 0; + for (Map.Entry<String, Object> entry : jMap.entrySet()) { + Object ot = entry.getValue(); + String value = ot + ""; + if (ot instanceof String) { + value = "'" + value.replace("'", "''") + "'"; + } + sqlString.append("'" + entry.getKey() + "':" + value); + if (counter != jMap.size() - 1) + sqlString.append(lineDelimiter); + counter = counter + 1; + } + return sqlString.toString(); + } + + public static Map<String, HashMap<String, Object>> setErrorResponse(MusicServiceException ex) { + Map<String, HashMap<String, Object>> results = new HashMap<>(); + HashMap<String, Object> tempMap = new HashMap<>(); + Map<String, Object> result = new HashMap<>(); + result.put("error-description", ex.getMessage()); + tempMap.put("error", result); + results.put("result", tempMap); + return results; + } } diff --git a/src/main/java/org/onap/music/main/PropertiesListener.java b/src/main/java/org/onap/music/main/PropertiesListener.java index de231542..afd35387 100755 --- a/src/main/java/org/onap/music/main/PropertiesListener.java +++ b/src/main/java/org/onap/music/main/PropertiesListener.java @@ -32,6 +32,9 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; @WebListener public class PropertiesListener implements ServletContextListener { @@ -127,6 +130,7 @@ public class PropertiesListener implements ServletContextListener { } } } catch (IOException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.IOERROR ,ErrorSeverity.CRITICAL, ErrorTypes.CONNECTIONERROR); logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); } diff --git a/src/main/java/org/onap/music/main/ResultType.java b/src/main/java/org/onap/music/main/ResultType.java index f19ada4a..6b0c5252 100644 --- a/src/main/java/org/onap/music/main/ResultType.java +++ b/src/main/java/org/onap/music/main/ResultType.java @@ -22,7 +22,8 @@ package org.onap.music.main; public enum ResultType { - SUCCESS("Success"), FAILURE("Failure"); + SUCCESS("Success"), FAILURE("Failure"), + SYNTAXERROR("SyntaxError"), EXCEPTION("Exception"); private String result; diff --git a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java index 0265d039..cbe9ec9c 100755 --- a/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicAdminAPI.java @@ -39,6 +39,9 @@ import javax.ws.rs.core.MediaType; import org.onap.music.datastore.PreparedQueryObject; import org.onap.music.datastore.jsonobjects.JsonOnboard; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.main.CachingUtil; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; @@ -72,6 +75,7 @@ public class RestMusicAdminAPI { String password = jsonObj.getPassword(); response.addHeader("X-latestVersion", MusicUtil.getVersion()); if (appName == null || userId == null || isAAF == null || password == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR); resultMap.put("Exception", "Please check the request parameters. Some of the required values appName(ns), userId, password, isAAF are missing."); return resultMap; @@ -163,8 +167,14 @@ public class RestMusicAdminAPI { Row row = (Row) it.next(); resultMap.put( row.getUUID("uuid").toString(),row.getString("keyspace_name")); } - if (resultMap.isEmpty()) - resultMap.put("ERROR", "Application is not onboarded. Please contact admin."); + if (resultMap.isEmpty()) { + if(uuid != null) + resultMap.put("Exception", "Please make sure Aid is correct and application is onboarded."); + else { + resultMap.put("Exception", + "Application is not onboarded. Please make sure all the information is correct."); + } + } return resultMap; } @@ -195,7 +205,7 @@ public class RestMusicAdminAPI { String ks = row.getString("keyspace_name"); if (!ks.equals(MusicUtil.DEFAULTKEYSPACENAME)) { PreparedQueryObject queryObject = new PreparedQueryObject(); - queryObject.appendQueryString("DROP KEYSPACE " + ks + ";"); + queryObject.appendQueryString("DROP KEYSPACE IF EXISTS " + ks + ";"); MusicCore.nonKeyRelatedPut(queryObject, consistency); } } @@ -208,7 +218,7 @@ public class RestMusicAdminAPI { resultMap.put("Success", "Your application has been deleted successfully"); } else { resultMap.put("Exception", - "Oops. Spomething went wrong. Please make sure Aid is correct or Application is onboarded"); + "Oops. Something went wrong. Please make sure Aid is correct or Application is onboarded"); } return resultMap; } @@ -325,7 +335,7 @@ public class RestMusicAdminAPI { resultMap.put("Success", "Your application has been updated successfully"); } else { resultMap.put("Exception", - "Oops. Spomething went wrong. Please make sure Aid is correct and application is onboarded"); + "Oops. Something went wrong. Please make sure Aid is correct and application is onboarded"); } return resultMap; diff --git a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java index f1d88efa..e7af8f9f 100755 --- a/src/main/java/org/onap/music/rest/RestMusicDataAPI.java +++ b/src/main/java/org/onap/music/rest/RestMusicDataAPI.java @@ -43,6 +43,10 @@ import org.onap.music.datastore.jsonobjects.JsonKeySpace; import org.onap.music.datastore.jsonobjects.JsonTable; import org.onap.music.datastore.jsonobjects.JsonUpdate; import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.exceptions.MusicLockingException; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicServiceException; import org.onap.music.main.CachingUtil; import org.onap.music.main.MusicCore; @@ -51,6 +55,8 @@ import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; import org.onap.music.response.jsonobjects.JsonResponse; + +import com.att.eelf.configuration.EELFLogger; import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; @@ -144,15 +150,21 @@ public class RestMusicDataAPI { JsonKeySpace kspObject, @ApiParam(value = "Keyspace Name", required = true) @PathParam("name") String keyspaceName, - @Context HttpServletResponse response) throws Exception { + @Context HttpServletResponse response) { Map<String, Object> resultMap = CachingUtil.verifyOnboarding(ns, userId, password); response.addHeader(xLatestVersion, MusicUtil.getVersion()); if (!resultMap.isEmpty()) { return resultMap; } - resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, - "createKeySpace"); + try { + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid, + "createKeySpace"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.applicationLogger, + "Exception while authenting the user."); + return resultMap; + } String newAid = null; if (!resultMap.isEmpty()) { if (resultMap.containsKey("aid")) { @@ -169,7 +181,12 @@ public class RestMusicDataAPI { boolean result = false; long start = System.currentTimeMillis(); Map<String, Object> replicationInfo = kspObject.getReplicationInfo(); - String repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + String repString = null; + try { + repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}"; + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + } queryObject.appendQueryString( "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString); if (kspObject.getDurabilityOfWrites() != null) { @@ -200,7 +217,12 @@ public class RestMusicDataAPI { queryObject.appendQueryString( "DELETE FROM admin.keyspace_master where uuid = " + newAid); queryObject.appendQueryString(";"); - result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + try { + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + resultMap.put("Exception", e.getMessage()); + } resultMap.remove("aid"); resultMap.remove("uuid"); return resultMap; @@ -209,10 +231,23 @@ public class RestMusicDataAPI { queryObject = new PreparedQueryObject(); queryObject.appendQueryString( "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;"); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), MusicUtil.DEFAULTKEYSPACENAME)); - queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); - result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + resultMap.put("Exception", "Unable to process input data. Invalid input data type. " + + "Please check keyspace_name and aid.. "); + } + try { + result = MusicCore.nonKeyRelatedPut(queryObject, consistency); + } catch (MusicServiceException e) { + e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, "Unable to process operation. Error: "+e.getMessage()); + resultMap.put("Exception", "Unable to process operation. Error: "+e.getMessage()); + return resultMap; + } resultMap.remove("aid"); resultMap.remove("uuid"); return resultMap; @@ -230,11 +265,18 @@ public class RestMusicDataAPI { queryObject.appendQueryString(";"); result = MusicCore.nonKeyRelatedPut(queryObject, consistency); } catch (Exception e) { - logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); } resultMap.remove("uuid"); - if (CachingUtil.isAAFApplication(ns)) - resultMap.remove("aid"); + try { + if (CachingUtil.isAAFApplication(ns)) + resultMap.remove("aid"); + } catch (MusicServiceException e) { + e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + resultMap.put("Exception", e.getMessage()); + return resultMap; + } resultMap.put("Status", String.valueOf(result)); return resultMap; @@ -348,6 +390,7 @@ public class RestMusicDataAPI { @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, @Context HttpServletResponse response) throws Exception { + Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "createTable"); response.addHeader(xLatestVersion, MusicUtil.getVersion()); @@ -366,11 +409,17 @@ public class RestMusicDataAPI { int counter = 0; String primaryKey; for (Map.Entry<String, String> entry : fields.entrySet()) { - fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); + if (entry.getKey().equals("PRIMARY KEY")) { - primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1); - primaryKey = primaryKey.substring(0, primaryKey.indexOf(')')); - } + if(! entry.getValue().contains("(")) + primaryKey = entry.getValue(); + else { + primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1); + primaryKey = primaryKey.substring(0, primaryKey.indexOf(')')); + } + fieldsString.append("" + entry.getKey() + " (" + primaryKey + ")"); + } else + fieldsString.append("" + entry.getKey() + " " + entry.getValue() + ""); if (counter == fields.size() - 1) fieldsString.append(")"); else @@ -500,9 +549,15 @@ public class RestMusicDataAPI { required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, - @Context HttpServletResponse response) throws Exception { - Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "insertIntoTable"); + @Context HttpServletResponse response) { + Map<String, Object> resultMap = null; + try { + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "insertIntoTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } response.addHeader(xLatestVersion, MusicUtil.getVersion()); if (resultMap.containsKey("aid")) resultMap.remove("aid"); @@ -512,7 +567,17 @@ public class RestMusicDataAPI { ReturnType result = null; Map<String, Object> valuesMap = insObj.getValues(); PreparedQueryObject queryObject = new PreparedQueryObject(); - TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + TableMetadata tableInfo = null; + try { + tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + if(tableInfo == null) + throw new MusicServiceException("Table name doesn't exists. Please check the table name."); + } catch (MusicServiceException e) { + e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + resultMap.put(ResultType.SYNTAXERROR.getResult(), e.getMessage()); + return resultMap; + } String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName(); StringBuilder fieldsString = new StringBuilder("(vector_ts,"); String vectorTs = @@ -532,7 +597,13 @@ public class RestMusicDataAPI { DataType colType = tableInfo.getColumn(entry.getKey()).getType(); - Object formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + Object formattedValue = null; + try { + formattedValue = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + //return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } valueString.append("?"); queryObject.addValue(formattedValue); @@ -593,7 +664,7 @@ public class RestMusicDataAPI { : new ReturnType(ResultType.FAILURE, "Null result - Please Contact admin").toMap(); } catch (Exception ex) { - logger.info(EELFLoggerDelegate.applicationLogger, ex.getMessage()); + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR); return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap(); } } @@ -631,9 +702,15 @@ public class RestMusicDataAPI { required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, - @Context UriInfo info, @Context HttpServletResponse response) throws Exception { - Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "updateTable"); + @Context UriInfo info, @Context HttpServletResponse response) { + Map<String, Object> resultMap; + try { + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "updateTable"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } response.addHeader(xLatestVersion, MusicUtil.getVersion()); if (resultMap.containsKey("aid")) resultMap.remove("aid"); @@ -651,7 +728,15 @@ public class RestMusicDataAPI { PreparedQueryObject queryObject = new PreparedQueryObject(); Map<String, Object> valuesMap = updateObj.getValues(); - TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + TableMetadata tableInfo; + try { + tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename); + } catch (MusicServiceException e) { + e.printStackTrace(); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage()); + resultMap.put("Exception", e.getMessage()); + return resultMap; + } if (tableInfo == null) { return new ReturnType(ResultType.FAILURE, "Table information not found. Please check input for table name= " @@ -665,7 +750,13 @@ public class RestMusicDataAPI { for (Map.Entry<String, Object> entry : valuesMap.entrySet()) { Object valueObj = entry.getValue(); DataType colType = tableInfo.getColumn(entry.getKey()).getType(); - Object valueString = MusicUtil.convertToActualDataType(colType, valueObj); + Object valueString = null; + try { + valueString = MusicUtil.convertToActualDataType(colType, valueObj); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + //return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } fieldValueString.append(entry.getKey() + "= ?"); queryObject.addValue(valueString); if (counter != valuesMap.size() - 1) @@ -699,7 +790,12 @@ public class RestMusicDataAPI { RowIdentifier rowId = null; try { rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject); + if(rowId == null || rowId.primarKeyValue.isEmpty()) { + resultMap.put(ResultType.SYNTAXERROR.getResult(), "Mandatory WHERE clause is missing. Please check the input request."); + return resultMap; + } } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage()); return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap(); } @@ -730,11 +826,21 @@ public class RestMusicDataAPI { queryObject, lockId, conditionInfo); } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) { // this function is mainly for the benchmarks - operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, - rowId.primarKeyValue, queryObject, conditionInfo); + try { + operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, + rowId.primarKeyValue, queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); + try { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } catch (MusicLockingException e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap(); + } } long actualUpdateCompletionTime = System.currentTimeMillis(); @@ -788,15 +894,25 @@ public class RestMusicDataAPI { required = true) @PathParam("keyspace") String keyspace, @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename, - @Context UriInfo info, @Context HttpServletResponse response) throws Exception { - Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, - aid, "deleteFromTable"); + @Context UriInfo info, @Context HttpServletResponse response) { + Map<String, Object> resultMap = null; + try { + resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace, + aid, "deleteFromTable"); + } catch (Exception e) { + resultMap.put("Exception", e.getMessage()); + return resultMap; + } response.addHeader(xLatestVersion, MusicUtil.getVersion()); if (resultMap.containsKey("aid")) resultMap.remove("aid"); if (!resultMap.isEmpty()) { return resultMap; } + if(delObj == null) { + resultMap.put("Exception", "Request body is missing. Please check your input data and retry."); + return resultMap; + } PreparedQueryObject queryObject = new PreparedQueryObject(); StringBuilder columnString = new StringBuilder(); @@ -851,21 +967,25 @@ public class RestMusicDataAPI { String consistency = delObj.getConsistencyInfo().get("type"); ReturnType operationResult = null; - - if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) - operationResult = MusicCore.eventualPut(queryObject); - else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { - String lockId = delObj.getConsistencyInfo().get("lockId"); - operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, lockId, conditionInfo); - } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { - operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } - else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { - operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, - queryObject, conditionInfo); - } + try { + if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) + operationResult = MusicCore.eventualPut(queryObject); + else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) { + String lockId = delObj.getConsistencyInfo().get("lockId"); + operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, lockId, conditionInfo); + } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) { + operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) { + operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, + queryObject, conditionInfo); + } + } catch (MusicLockingException e) { + resultMap.put("Exception", "Unable to perform Delete operation. Exception from music: "+e.getMessage()); + return resultMap; + } try { return operationResult.toMap(); } catch (NullPointerException e) { @@ -1039,7 +1159,7 @@ public class RestMusicDataAPI { if (resultMap.containsKey("aid")) resultMap.remove("aid"); if (!resultMap.isEmpty()) { - logger.error("Error while authentication... "); + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); HashMap<String, Object> tempMap = new HashMap<>(); tempMap.putAll(resultMap); Map<String, HashMap<String, Object>> results = new HashMap<>(); @@ -1064,6 +1184,7 @@ public class RestMusicDataAPI { ResultSet results = MusicCore.get(queryObject); return MusicCore.marshallResults(results); } catch (MusicServiceException ex) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR); return MusicUtil.setErrorResponse(ex); } @@ -1077,7 +1198,6 @@ public class RestMusicDataAPI { * @param limit * @return * @throws MusicServiceException - * @throws Exception */ public PreparedQueryObject selectSpecificQuery(String version, String minorVersion, String patchVersion, String aid, String ns, String userId, String password, @@ -1108,7 +1228,6 @@ public class RestMusicDataAPI { * @param queryObject * @return * @throws MusicServiceException - * @throws Exception */ private RowIdentifier getRowIdentifier(String keyspace, String tablename, MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject) @@ -1130,7 +1249,12 @@ public class RestMusicDataAPI { List<String> valueList = entry.getValue(); String indValue = valueList.get(0); DataType colType = tableInfo.getColumn(entry.getKey()).getType(); - Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + Object formattedValue = null; + try { + formattedValue = MusicUtil.convertToActualDataType(colType, indValue); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,e.getMessage()); + } primaryKey.append(indValue); rowSpec.append(keyName + "= ?"); queryObject.addValue(formattedValue); diff --git a/src/test/java/org/onap/music/benchmarks/MicroBenchMarkRestClient.java b/src/test/java/org/onap/music/benchmarks/MicroBenchMarkRestClient.java deleted file mode 100644 index 2dcecfc2..00000000 --- a/src/test/java/org/onap/music/benchmarks/MicroBenchMarkRestClient.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ -package org.onap.music.benchmarks; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.onap.music.main.MusicUtil; - - -@Path("/tests") -public class MicroBenchMarkRestClient { - static double version = 9.7; - - @GET - @Path("/run") - @Produces(MediaType.TEXT_PLAIN) - public String runTests() { - String testType = MusicUtil.getTestType(); - String candidateName = "shankar" + System.currentTimeMillis(); - MicroBenchMarks msHandle = new MicroBenchMarks(); - switch (testType) { - case "musicPut": - return msHandle.musicPutAndUpdate(candidateName); - - case "musicCriticalPut": - return msHandle.musicCriticalPutAndUpdate(candidateName); - - case "musicGet": - return msHandle.musicGet(); - - case "cassaPut": - return msHandle.cassaPutAndUpdate(candidateName); - - case "cassaQuorumPut": - return msHandle.cassaQuorumPutAndUpdate(candidateName); - - case "cassaGet": - return msHandle.cassaGet(); - - case "zkPut": - return msHandle.zkPutAndUpdate(candidateName); - - case "zkGet": - return msHandle.zkGet(); - - } - return "something wrong!"; - - } - -} - diff --git a/src/test/java/org/onap/music/benchmarks/MicroBenchMarks.java b/src/test/java/org/onap/music/benchmarks/MicroBenchMarks.java deleted file mode 100644 index c267d254..00000000 --- a/src/test/java/org/onap/music/benchmarks/MicroBenchMarks.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ -package org.onap.music.benchmarks; - -import java.util.HashMap; -import java.util.Map; -import javax.ws.rs.core.MediaType; -import org.onap.music.datastore.jsonobjects.JsonInsert; -import org.onap.music.datastore.jsonobjects.JsonKeySpace; -import org.onap.music.datastore.jsonobjects.JsonTable; -import org.onap.music.main.MusicUtil; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.json.JSONConfiguration; - -public class MicroBenchMarks { - final String keyspaceName = "shankarks"; - final String musicurl = "http://" + MusicUtil.getMusicRestIp() + ":8080/MUSIC/rest/formal"; - final String userForGets = "shankarUserForGets"; - - public MicroBenchMarks() { - bootStrap(); - } - - private void createVotingKeyspace() { - System.out.println(keyspaceName); - Map<String, Object> replicationInfo = new HashMap<String, Object>(); - replicationInfo.put("class", "SimpleStrategy"); - replicationInfo.put("replication_factor", 3); - String durabilityOfWrites = "false"; - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - JsonKeySpace jsonKp = new JsonKeySpace(); - jsonKp.setConsistencyInfo(consistencyInfo); - jsonKp.setDurabilityOfWrites(durabilityOfWrites); - jsonKp.setReplicationInfo(replicationInfo); - - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - WebResource webResource = client.resource(musicurl + "/keyspaces/" + keyspaceName); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jsonKp); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - } - - private void createVotingTable() { - Map<String, String> fields = new HashMap<String, String>(); - fields.put("name", "text"); - fields.put("count", "varint"); - fields.put("PRIMARY KEY", "(name)"); - - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonTable jtab = new JsonTable(); - jtab.setFields(fields); - jtab.setConsistencyInfo(consistencyInfo); - - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - WebResource webResource = client - .resource(musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount"); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jtab); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - } - - private void createEntryForCandidate(String candidateName) { - Map<String, Object> values = new HashMap<String, Object>(); - values.put("name", candidateName); - values.put("count", 0); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - String url = musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount/rows"; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - private String createLock(String lockName) { - Client client = Client.create(); - String msg = musicurl + "/locks/create/" + lockName; - WebResource webResource = client.resource(msg); - System.out.println(msg); - - WebResource.Builder wb = webResource.accept(MediaType.TEXT_PLAIN); - - ClientResponse response = wb.post(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - String output = response.getEntity(String.class); - - return output; - } - - private boolean acquireLock(String lockId) { - Client client = Client.create(); - String msg = musicurl + "/locks/acquire/" + lockId; - System.out.println(msg); - WebResource webResource = client.resource(msg); - - - WebResource.Builder wb = webResource.accept(MediaType.TEXT_PLAIN); - - ClientResponse response = wb.get(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - String output = response.getEntity(String.class); - Boolean status = Boolean.parseBoolean(output); - System.out.println("Server response .... \n"); - System.out.println(output); - return status; - } - - private void unlock(String lockId) { - Client client = Client.create(); - WebResource webResource = client.resource(musicurl + "/locks/release/" + lockId); - - ClientResponse response = webResource.delete(ClientResponse.class); - - - if (response.getStatus() != 204) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - } - - public String musicCriticalPutAndUpdate(String candidateName) { - /* - * create lock for the candidate. The music API dictates that the lock name must be of the - * form keyspacename.tableName.primaryKeyName - */ - createEntryForCandidate(candidateName); - System.out.println("trying to acquire lock!"); - - String lockName = keyspaceName + ".votecount." + candidateName; - String lockId = createLock(lockName); - while (acquireLock(lockId) != true); - - System.out.println("acquired lock!"); - // update candidate entry if you have the lock - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", 5); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "atomic"); - consistencyInfo.put("lockId", lockId); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount/rows?name=" - + candidateName; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - // release lock now that the operation is done - unlock(lockId); - return "musicCriticalPutAndUpdate:" + url; - - } - - public String musicPutAndUpdate(String candidateName) { - createEntryForCandidate(candidateName); - - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", 5); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount/rows?name=" - + candidateName; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - return "musicPutAndUpdate:" + url; - } - - public String musicGet() { - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - String url = musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount/rows?name=" - + userForGets; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").get(ClientResponse.class); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - Map<String, Object> output = response.getEntity(Map.class); - return "musicGet:" + url; - } - - public String cassaQuorumPutAndUpdate(String candidateName) { - // http://135.197.226.98:8080/MUSIC/rest/formal/purecassa/keyspaces/shankarks/tables/employees/rows?emp_name=shankaruser1 - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", 5); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "atomic"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicurl + "/purecassa/keyspaces/" + keyspaceName - + "/tables/votecount/rows?name=" + candidateName; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - return "cassaQuorumPutAndUpdate:" + url; - - } - - public String cassaPutAndUpdate(String candidateName) { - // http://135.197.226.98:8080/MUSIC/rest/formal/purecassa/keyspaces/shankarks/tables/employees/rows?emp_name=shankaruser1 - long start = System.currentTimeMillis(); - createEntryForCandidate(candidateName); - - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", 5); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicurl + "/purecassa/keyspaces/" + keyspaceName - + "/tables/votecount/rows?name=" + candidateName; - WebResource webResource = client.resource(url); - long end = System.currentTimeMillis(); - String time = (end - start) + ""; - - start = System.currentTimeMillis(); - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - end = System.currentTimeMillis(); - String time2 = (end - start) + ""; - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - return "cassaPutAndUpdate:" + url; - } - - public String cassaGet() { - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - String url = musicurl + "/keyspaces/" + keyspaceName + "/tables/votecount/rows?name=" - + userForGets; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").get(ClientResponse.class); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - Map<String, Object> output = response.getEntity(Map.class); - return "cassaGet:" + url; - } - - private void zkCreate(String candidateName) { - // http://135.197.226.98:8080/MUSIC/rest/formal/purezk/shankarzknode - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - WebResource webResource = client.resource(musicurl + "/purezk/" + candidateName); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - public String zkPutAndUpdate(String candidateName) { - // http://135.197.226.99:8080/MUSIC/rest/formal/purezk/shankarzknode - - // CREATE IT FIRST - zkCreate(candidateName); - - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", 5); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "atomic"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicurl + "/purezk/" + candidateName; - System.out.println("in zk put:" + url); - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - return "zkPutAndUpdate:" + url; - } - - public String zkGet() { - Client client = Client.create(); - String url = musicurl + "/purezk/" + userForGets; - System.out.println("in zk get:" + url); - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("text/plain").get(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - String output = response.getEntity(String.class); - return "zkGet:" + url; - } - - - public void bootStrap() { - // createVotingKeyspace(); - // createVotingTable(); - // createEntryForCandidate(userForGets); - // zkPutAndUpdate(userForGets); - } - - -} diff --git a/src/test/java/org/onap/music/e2eTests/MusicConnector.java b/src/test/java/org/onap/music/e2eTests/MusicConnector.java deleted file mode 100644 index bb3d1f1b..00000000 --- a/src/test/java/org/onap/music/e2eTests/MusicConnector.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ -package org.onap.music.e2eTests; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Random; - -public class MusicConnector { - - // change this to point to relevant cluster - public String[] musicNodes; - - public MusicConnector(String[] musicNodes) { - this.musicNodes = musicNodes; - } - - private String getMusicNodeIp() { - Random r = new Random(); - int index = r.nextInt(musicNodes.length); - return musicNodes[index]; - } - - /* - * public static String toggle(String serverAddress){ if(serverAddress.equals(agaveMusicNode)){ - * System.out.println("Agave is down...connect to Big Site"); serverAddress = bigSiteMusicNode; - * }else if(serverAddress.equals(bigSiteMusicNode)){ - * System.out.println("Big Site is down...connect to Agave"); serverAddress = agaveMusicNode; } - * return serverAddress; } - */ - - public String getMusicNodeURL() { - String musicurl = "http://" + getMusicNodeIp() + ":8080/MUSIC/rest"; - System.out.println(musicurl); - return musicurl; - } - - public boolean isHostUp(String serverAddress) { - Boolean isUp = false; - try { - InetAddress inet = InetAddress.getByName(serverAddress); - isUp = inet.isReachable(1000); - } catch (UnknownHostException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return isUp; - } - - /* - * private static String getMusicNodeIp(){ - * - * //return "54.224.168.13"; return bigSiteMusicNode; String serverAddress; serverAddress = - * agaveMusicNode; while(isHostUp(serverAddress) != true) serverAddress = toggle(serverAddress); - * return serverAddress; } - */ -} diff --git a/src/test/java/org/onap/music/e2eTests/TestMusicE2E.java b/src/test/java/org/onap/music/e2eTests/TestMusicE2E.java deleted file mode 100644 index 25021e82..00000000 --- a/src/test/java/org/onap/music/e2eTests/TestMusicE2E.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * ============LICENSE_START========================================== - * org.onap.music - * =================================================================== - * Copyright (c) 2017 AT&T Intellectual Property - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ============LICENSE_END============================================= - * ==================================================================== - */ -package org.onap.music.e2eTests; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import javax.ws.rs.core.MediaType; -import org.onap.music.datastore.jsonobjects.JsonDelete; -import org.onap.music.datastore.jsonobjects.JsonInsert; -import org.onap.music.datastore.jsonobjects.JsonKeySpace; -import org.onap.music.datastore.jsonobjects.JsonTable; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.json.JSONConfiguration; - -public class TestMusicE2E { - String keyspaceName; - ArrayList<String> lockNames; - MusicConnector musicHandle; - - public TestMusicE2E(String[] musicIps) { - lockNames = new ArrayList<String>(); - musicHandle = new MusicConnector(musicIps); - bootStrap(); - } - - public void createVotingKeyspace() { - keyspaceName = "VotingAppForMusic" + System.currentTimeMillis(); - Map<String, Object> replicationInfo = new HashMap<String, Object>(); - replicationInfo.put("class", "SimpleStrategy"); - replicationInfo.put("replication_factor", 1); - String durabilityOfWrites = "false"; - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - JsonKeySpace jsonKp = new JsonKeySpace(); - jsonKp.setConsistencyInfo(consistencyInfo); - jsonKp.setDurabilityOfWrites(durabilityOfWrites); - jsonKp.setReplicationInfo(replicationInfo); - - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - WebResource webResource = client - .resource(musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jsonKp); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - } - - public void createVotingTable() { - Map<String, String> fields = new HashMap<String, String>(); - fields.put("name", "text"); - fields.put("count", "varint"); - fields.put("PRIMARY KEY", "(name)"); - - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonTable jtab = new JsonTable(); - jtab.setFields(fields); - jtab.setConsistencyInfo(consistencyInfo); - - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount"; - System.out.println("create url:" + url); - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jtab); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - } - - private void checkMusicVersion() { - Client client = Client.create(); - System.out.println(musicHandle.getMusicNodeURL() + "/version"); - - - // System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); - WebResource webResource = client.resource(musicHandle.getMusicNodeURL() + "/version"); - - - ClientResponse response = webResource.accept("text/plain").header("Connection", "close") - .get(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - String output = response.getEntity(String.class); - - // System.out.println("Output from Server .... \n"); - System.out.println(output); - - } - - private void createEntryForCandidate(String candidateName) { - Map<String, Object> values = new HashMap<String, Object>(); - values.put("name", candidateName); - values.put("count", 0); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount/rows"; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .post(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus() + "url:" - + url + " candidate name:" + candidateName); - - - } - - private String createLock(String lockName) { - Client client = Client.create(); - String msg = musicHandle.getMusicNodeURL() + "/locks/create/" + lockName; - WebResource webResource = client.resource(msg); - System.out.println(msg); - WebResource.Builder wb = webResource.accept(MediaType.TEXT_PLAIN); - - ClientResponse response = wb.post(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException( - "Failed : HTTP error code : " + response.getStatus() + "url:" + msg); - } - - String output = response.getEntity(String.class); - - // System.out.println("Server response .... \n"); - // System.out.println(output); - return output; - } - - private boolean acquireLock(String lockId) { - Client client = Client.create(); - String msg = musicHandle.getMusicNodeURL() + "/locks/acquire/" + lockId; - System.out.println(msg); - WebResource webResource = client.resource(msg); - - - WebResource.Builder wb = webResource.accept(MediaType.TEXT_PLAIN); - - ClientResponse response = wb.get(ClientResponse.class); - - if (response.getStatus() != 200) { - throw new RuntimeException( - "Failed : HTTP error code : " + response.getStatus() + "url:" + msg); - } - - String output = response.getEntity(String.class); - Boolean status = Boolean.parseBoolean(output); - System.out.println("Server response .... \n"); - System.out.println(output); - return status; - } - - private void unlock(String lockId) { - Client client = Client.create(); - WebResource webResource = - client.resource(musicHandle.getMusicNodeURL() + "/locks/release/" + lockId); - - ClientResponse response = webResource.delete(ClientResponse.class); - - - if (response.getStatus() != 204) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - } - - private void updateVoteCountAtomically(String candidateName, int count) { - /* - * create lock for the candidate. The music API dictates that the lock name must be of the - * form keyspacename.tableName.primaryKeyName - */ - System.out.println("trying to acquire lock!"); - - String lockName = keyspaceName + ".votecount." + candidateName; - lockNames.add(lockName); - String lockId = createLock(lockName); - while (acquireLock(lockId) != true); - - System.out.println("acquired lock!"); - // update candidate entry if you have the lock - Map<String, Object> values = new HashMap<String, Object>(); - values.put("count", count); - - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "critical"); - consistencyInfo.put("lockId", lockId); - - JsonInsert jIns = new JsonInsert(); - jIns.setValues(values); - jIns.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount/rows?name=" + candidateName; - System.out.println(url); - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .put(ClientResponse.class, jIns); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException( - "Failed : HTTP error code : " + response.getStatus() + "url:" + url); - - // release lock now that the operation is done - unlock(lockId); - - } - - private void deleteCandidateEntryEventually(String candidateName) { - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonDelete jDel = new JsonDelete(); - jDel.setConsistencyInfo(consistencyInfo); - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount/rows?name=" + candidateName; - System.out.println(url); - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").type("application/json") - .delete(ClientResponse.class, jDel); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException( - "Failed : HTTP error code : " + response.getStatus() + "url:" + url); - - } - - public Map<String, Object> readVoteCountForCandidate(String candidateName) { - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount/rows?name=" + candidateName; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").get(ClientResponse.class); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - Map<String, Object> output = response.getEntity(Map.class); - return output; - } - - public Map<String, Object> readAllVotes() { - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - String url = musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName - + "/tables/votecount/rows"; - WebResource webResource = client.resource(url); - - ClientResponse response = webResource.accept("application/json").get(ClientResponse.class); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - - Map<String, Object> output = response.getEntity(Map.class); - return output; - } - - - /* - * Unable to use this because of the error: Exception in thread "main" - * com.sun.jersey.api.client.ClientHandlerException: java.net.ProtocolException: HTTP method - * DELETE doesn't support output. Seems to be a error in the rest java combination according to - * the interwebs - */ - private void dropKeySpace() { - Map<String, String> consistencyInfo = new HashMap<String, String>(); - consistencyInfo.put("type", "eventual"); - - JsonKeySpace jsonKp = new JsonKeySpace(); - jsonKp.setConsistencyInfo(consistencyInfo); - - ClientConfig clientConfig = new DefaultClientConfig(); - - clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - - Client client = Client.create(clientConfig); - - WebResource webResource = client - .resource(musicHandle.getMusicNodeURL() + "/keyspaces/" + keyspaceName); - - ClientResponse response = - webResource.type("application/json").delete(ClientResponse.class, jsonKp); - - if (response.getStatus() < 200 || response.getStatus() > 299) - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - private void deleteLock(String lockName) { - Client client = Client.create(); - WebResource webResource = client - .resource(musicHandle.getMusicNodeURL() + "/locks/delete/" + lockName); - - ClientResponse response = webResource.delete(ClientResponse.class); - - - if (response.getStatus() != 204) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - } - - private void resetMusic() { - Client client = Client.create(); - WebResource webResource = client.resource(musicHandle.getMusicNodeURL() + "/reset"); - - ClientResponse response = webResource.delete(ClientResponse.class); - - - if (response.getStatus() != 204) { - throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); - } - - } - - public void deleteAllLocks() { - for (String lockName : lockNames) { - deleteLock(lockName); - } - } - - - public void bootStrap() { - checkMusicVersion(); - createVotingKeyspace(); - - - createVotingTable(); - - - // the next few lines just create an entry in the voting table for all these candidates with - // vote count as 0 - createEntryForCandidate("Popeye"); - - createEntryForCandidate("Judy"); - - createEntryForCandidate("Flash"); - - createEntryForCandidate("Mickey"); - - } - - public void overAllTests() { - // update the count atomically - updateVoteCountAtomically("Popeye", 5); - - updateVoteCountAtomically("Judy", 7); - - updateVoteCountAtomically("Mickey", 8); - - updateVoteCountAtomically("Flash", 2); - - - // read votecount - System.out.println(readAllVotes()); - - System.out.println(readVoteCountForCandidate("Popeye")); - - System.out.println(readVoteCountForCandidate("Flash")); - - deleteCandidateEntryEventually("Mickey"); - - System.out.println(readAllVotes()); - - dropKeySpace(); - - deleteAllLocks(); - } - - public void flipTest() { - checkMusicVersion(); - } - - public static String executeBashScript(String pathToScript, String arg1, String arg2) { - try { - ProcessBuilder pb = new ProcessBuilder(pathToScript, arg1, arg2); - final Process process = pb.start(); - InputStream is = process.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - return br.readLine(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public static void main(String[] args) { - long start = System.currentTimeMillis(); - for (int i = 0; i < 2; ++i) { - TestMusicE2E vHandle = new TestMusicE2E(args); - vHandle.overAllTests(); - - System.out.println("====================================="); - System.out.println("Test no." + i + " completed:"); - } - long diff = System.currentTimeMillis() - start; - System.out.println(diff); - } - - -} diff --git a/src/test/java/org/onap/music/unittests/CassandraCQL.java b/src/test/java/org/onap/music/unittests/CassandraCQL.java index ed8f13f4..a4c250c2 100644 --- a/src/test/java/org/onap/music/unittests/CassandraCQL.java +++ b/src/test/java/org/onap/music/unittests/CassandraCQL.java @@ -232,13 +232,14 @@ public class CassandraCQL { try { try { - EmbeddedCassandraServerHelper.startEmbeddedCassandra(60000); + EmbeddedCassandraServerHelper.startEmbeddedCassandra(80000); } catch (ConfigurationException | TTransportException | IOException e) { System.out.println(e.getMessage()); } cluster = new Cluster.Builder().addContactPoint(address).withPort(9142).build(); + cluster.getConfiguration().getSocketOptions().setReadTimeoutMillis(20000); session = cluster.connect(); break; diff --git a/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java b/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java index 520a5fe4..16d2af02 100644 --- a/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java +++ b/src/test/java/org/onap/music/unittests/MusicDataStoreTest.java @@ -22,6 +22,7 @@ package org.onap.music.unittests; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -34,113 +35,128 @@ import org.onap.music.exceptions.MusicServiceException; import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.PreparedQueryObject; + +import com.datastax.driver.core.DataType; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; +import com.datastax.driver.core.TableMetadata; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class MusicDataStoreTest { - static MusicDataStore dataStore; - static PreparedQueryObject testObject; + static MusicDataStore dataStore; + static PreparedQueryObject testObject; - @BeforeClass - public static void init() { - dataStore = CassandraCQL.connectToEmbeddedCassandra(); + @BeforeClass + public static void init() { + dataStore = CassandraCQL.connectToEmbeddedCassandra(); - } + } - @AfterClass - public static void close() throws MusicServiceException, MusicQueryException { + @AfterClass + public static void close() throws MusicServiceException, MusicQueryException { - testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.dropKeyspace); - dataStore.executePut(testObject, "eventual"); - dataStore.close(); - - } - - @Test - public void Test1_SetUp() throws MusicServiceException, MusicQueryException { - boolean result = false; - testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.createKeySpace); - result = dataStore.executePut(testObject, "eventual");; - testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.createTableEmployees); - result = dataStore.executePut(testObject, "eventual"); - assertEquals(true, result); - - } - - @Test - public void Test2_ExecutePut_eventual_insert() throws MusicServiceException, MusicQueryException { - testObject = CassandraCQL.setPreparedInsertQueryObject1(); - boolean result = dataStore.executePut(testObject, "eventual"); - assertEquals(true, result); - } - - @Test - public void Test3_ExecutePut_critical_insert() throws MusicServiceException, MusicQueryException { - testObject = CassandraCQL.setPreparedInsertQueryObject2(); - boolean result = dataStore.executePut(testObject, "Critical"); - assertEquals(true, result); - } - - @Test - public void Test4_ExecutePut_eventual_update() throws MusicServiceException, MusicQueryException { - testObject = CassandraCQL.setPreparedUpdateQueryObject(); - boolean result = false; - result = dataStore.executePut(testObject, "eventual"); - assertEquals(true, result); - } - - @Test - public void Test5_ExecuteEventualGet() throws MusicServiceException, MusicQueryException { - testObject = new PreparedQueryObject(); - testObject.appendQueryString(CassandraCQL.selectALL); - boolean result = false; - int count = 0; - ResultSet output = null; - output = dataStore.executeEventualGet(testObject); - System.out.println(output); - ; - for (Row row : output) { - count++; - System.out.println(row.toString()); - } - if (count == 2) { - result = true; - } - assertEquals(true, result); - } - - @Test - public void Test6_ExecuteCriticalGet() throws MusicServiceException, MusicQueryException { - testObject = CassandraCQL.setPreparedGetQuery(); - boolean result = false; - int count = 0; - ResultSet output = null; - output = dataStore.executeCriticalGet(testObject); - System.out.println(output); - ; - for (Row row : output) { - count++; - System.out.println(row.toString()); - } - if (count == 1) { - result = true; - } - assertEquals(true, result); - } - - @Test(expected = NullPointerException.class) - public void Test7_exception() { - PreparedQueryObject queryObject = null; - try { - dataStore.executePut(queryObject, "critical"); - } catch (MusicQueryException | MusicServiceException e) { - System.out.println(e.getMessage()); - } - - } + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.dropKeyspace); + dataStore.executePut(testObject, "eventual"); + dataStore.close(); + + } + + @Test + public void Test1_SetUp() throws MusicServiceException, MusicQueryException { + boolean result = false; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createKeySpace); + result = dataStore.executePut(testObject, "eventual");; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createTableEmployees); + result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + + } + + @Test + public void Test2_ExecutePut_eventual_insert() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedInsertQueryObject1(); + boolean result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + } + + @Test + public void Test3_ExecutePut_critical_insert() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedInsertQueryObject2(); + boolean result = dataStore.executePut(testObject, "Critical"); + assertEquals(true, result); + } + + @Test + public void Test4_ExecutePut_eventual_update() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedUpdateQueryObject(); + boolean result = false; + result = dataStore.executePut(testObject, "eventual"); + assertEquals(true, result); + } + + @Test + public void Test5_ExecuteEventualGet() throws MusicServiceException, MusicQueryException { + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.selectALL); + boolean result = false; + int count = 0; + ResultSet output = null; + output = dataStore.executeEventualGet(testObject); + System.out.println(output); + ; + for (Row row : output) { + count++; + System.out.println(row.toString()); + } + if (count == 2) { + result = true; + } + assertEquals(true, result); + } + + @Test + public void Test6_ExecuteCriticalGet() throws MusicServiceException, MusicQueryException { + testObject = CassandraCQL.setPreparedGetQuery(); + boolean result = false; + int count = 0; + ResultSet output = null; + output = dataStore.executeCriticalGet(testObject); + System.out.println(output); + ; + for (Row row : output) { + count++; + System.out.println(row.toString()); + } + if (count == 1) { + result = true; + } + assertEquals(true, result); + } + + @Test(expected = NullPointerException.class) + public void Test7_exception() { + PreparedQueryObject queryObject = null; + try { + dataStore.executePut(queryObject, "critical"); + } catch (MusicQueryException | MusicServiceException e) { + System.out.println(e.getMessage()); + } + } + + @Test + public void Test8_columnDataType() { + DataType data = dataStore.returnColumnDataType("testCassa", "employees", "empName"); + String datatype = data.toString(); + assertEquals("text",datatype); + } + + @Test + public void Test8_columnMetdaData() { + TableMetadata data = dataStore.returnColumnMetadata("testCassa", "employees"); + assertNotNull(data); + } } diff --git a/src/test/java/org/onap/music/unittests/MusicUtilTest.java b/src/test/java/org/onap/music/unittests/MusicUtilTest.java index 35ec3791..47edc1e3 100644 --- a/src/test/java/org/onap/music/unittests/MusicUtilTest.java +++ b/src/test/java/org/onap/music/unittests/MusicUtilTest.java @@ -73,11 +73,11 @@ public class MusicUtilTest { assertEquals(MusicUtil.getAllIds().get(0),"1"); } - @Test - public void testGetPublicIp() { - MusicUtil.setPublicIp("10.0.0.1"); - assertEquals(MusicUtil.getPublicIp(),"10.0.0.1"); - } +// @Test +// public void testGetPublicIp() { +// MusicUtil.setPublicIp("10.0.0.1"); +// assertEquals(MusicUtil.getPublicIp(),"10.0.0.1"); +// } @Test public void testGetAllPublicIps() { @@ -124,11 +124,11 @@ public class MusicUtilTest { assertEquals(MusicUtil.getVersion(),"1.0.0"); } - @Test + /*@Test public void testGetMyZkHost() { MusicUtil.setMyZkHost("10.0.0.2"); assertEquals(MusicUtil.getMyZkHost(),"10.0.0.2"); - } + }*/ @Test public void testGetMyCassaHost() { @@ -169,7 +169,7 @@ public class MusicUtilTest { } @Test - public void testConvertToCQLDataType() { + public void testConvertToCQLDataType() throws Exception { Map<String,Object> myMap = new HashMap<String,Object>(); myMap.put("name","tom"); assertEquals(MusicUtil.convertToCQLDataType(DataType.varchar(),"Happy People"),"'Happy People'"); @@ -179,7 +179,7 @@ public class MusicUtilTest { } @Test - public void testConvertToActualDataType() { + public void testConvertToActualDataType() throws Exception { assertEquals(MusicUtil.convertToActualDataType(DataType.varchar(),"Happy People"),"Happy People"); assertEquals(MusicUtil.convertToActualDataType(DataType.uuid(),"29dc2afa-c2c0-47ae-afae-e72a645308ab"),UUID.fromString("29dc2afa-c2c0-47ae-afae-e72a645308ab")); assertEquals(MusicUtil.convertToActualDataType(DataType.varint(),"1234"),BigInteger.valueOf(Long.parseLong("1234"))); @@ -195,7 +195,7 @@ public class MusicUtilTest { } @Test - public void testJsonMaptoSqlString() { + public void testJsonMaptoSqlString() throws Exception { Map<String,Object> myMap = new HashMap<>(); myMap.put("name","tom"); myMap.put("value",5); diff --git a/src/test/java/org/onap/music/unittests/TestMusicCore.java b/src/test/java/org/onap/music/unittests/TestMusicCore.java index 2deb3496..c571085a 100644 --- a/src/test/java/org/onap/music/unittests/TestMusicCore.java +++ b/src/test/java/org/onap/music/unittests/TestMusicCore.java @@ -37,12 +37,14 @@ import org.onap.music.lockingservice.MusicLockState; import org.onap.music.lockingservice.MusicLockingService; import org.onap.music.lockingservice.MusicLockState.LockStatus; import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; import org.onap.music.main.ResultType; import org.onap.music.main.ReturnType; import org.onap.music.main.MusicCore.Condition; import org.onap.music.datastore.MusicDataStore; import org.onap.music.datastore.PreparedQueryObject; import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; @RunWith(MockitoJUnitRunner.class) public class TestMusicCore { @@ -55,6 +57,9 @@ public class TestMusicCore { @Mock private PreparedQueryObject preparedQueryObject; + + @Mock + private Session session; @Before public void setUp() { @@ -145,6 +150,29 @@ public class TestMusicCore { assertEquals(lock.getMessage(), "Lockid doesn't exist"); Mockito.verify(mLockHandle).lockIdExists("bs1"); } + + @Test + public void testAcquireLockWithLeasewithLease() throws MusicLockingException { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + musicLockState.setLeasePeriod(0); + ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle).isMyTurn("id1"); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + } + + @Test + public void testAcquireLockWithLeasewithException() throws MusicLockingException { + ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "failure"); + Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenThrow(new MusicLockingException()); + Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); + ReturnType actualResult = MusicCore.acquireLockWithLease("ks1.tn1.pk1", "id1", 6000); + assertEquals(expectedResult.getResult(), actualResult.getResult()); + Mockito.verify(mLockHandle, Mockito.atLeastOnce()).getLockState("ks1.tn1.pk1"); + } @Test public void testAcquireLockWithLeasewithLockStatusLOCKED() throws MusicLockingException { @@ -183,15 +211,17 @@ public class TestMusicCore { Mockito.verify(mLockHandle).getLockState("ks1.tn1.pk1"); } - /* - * @Test public void testQuorumGet() { mDstoreHandle = Mockito.mock(MusicDataStore.class); rs = - * Mockito.mock(ResultSet.class); - * Mockito.when(mDstoreHandle.executeCriticalGet("qu1")).thenReturn(rs); ResultSet rs1 = - * MusicCore.quorumGet("qu1"); assertNotNull(rs1); - * Mockito.verify(mDstoreHandle).executeCriticalGet("qu1"); - * - * } - */ + @Test + public void testQuorumGet() throws MusicServiceException, MusicQueryException { + preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + mDstoreHandle = Mockito.mock(MusicDataStore.class); + rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); + Mockito.when(mDstoreHandle.executeCriticalGet(preparedQueryObject)).thenReturn(rs); + ResultSet rs1 = MusicCore.quorumGet(preparedQueryObject); + assertNotNull(rs1); + } @Test public void testGetLockNameFromId() { @@ -244,6 +274,8 @@ public class TestMusicCore { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "eventual")).thenReturn(true); ReturnType actualResult = MusicCore.eventualPut(preparedQueryObject); assertEquals(expectedResult.getResult(), actualResult.getResult()); @@ -256,19 +288,24 @@ public class TestMusicCore { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); ReturnType expectedResult = new ReturnType(ResultType.FAILURE, "Failure"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "eventual")).thenReturn(false); ReturnType actualResult = MusicCore.eventualPut(preparedQueryObject); assertEquals(expectedResult.getResult(), actualResult.getResult()); Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, "eventual"); + //Mockito.verify(mDstoreHandle).executePut(preparedQueryObject, MusicUtil.EVENTUAL); } @Test public void testCriticalPutPreparedQuerywithValidLockId() - throws MusicServiceException, MusicQueryException, MusicLockingException { + throws Exception { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); Mockito.when(condition.testCondition()).thenReturn(true); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) .thenReturn(musicLockState); @@ -296,7 +333,7 @@ public class TestMusicCore { } @Test - public void testCriticalPutPreparedQuerywithvalidLockIdandTestConditionFalse() throws MusicLockingException { + public void testCriticalPutPreparedQuerywithvalidLockIdandTestConditionFalse() throws Exception { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); @@ -315,6 +352,8 @@ public class TestMusicCore { public void testNonKeyRelatedPutPreparedQuery() throws Exception { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mDstoreHandle.executePut(preparedQueryObject, "consistency")).thenReturn(true); Boolean result = MusicCore.nonKeyRelatedPut(preparedQueryObject, "consistency"); assertTrue(result); @@ -322,12 +361,14 @@ public class TestMusicCore { } @Test - public void testAtomicPutPreparedQuery() throws MusicServiceException, MusicQueryException, MusicLockingException { + public void testAtomicPutPreparedQuery() throws Exception { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); ReturnType expectedResult = new ReturnType(ResultType.SUCCESS, "Succes"); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); Mockito.when(mLockHandle.isMyTurn("id1")).thenReturn(true); Mockito.when(condition.testCondition()).thenReturn(true); @@ -365,6 +406,8 @@ public class TestMusicCore { mDstoreHandle = Mockito.mock(MusicDataStore.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mLockHandle.createLockId("/" + "ks1.tn1.pk1")).thenReturn("id1"); MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); Mockito.when(mLockHandle.getLockState("ks1.tn1.pk1")).thenReturn(musicLockState); @@ -401,6 +444,8 @@ public class TestMusicCore { mDstoreHandle = Mockito.mock(MusicDataStore.class); rs = Mockito.mock(ResultSet.class); preparedQueryObject = Mockito.mock(PreparedQueryObject.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mDstoreHandle.executeEventualGet(preparedQueryObject)).thenReturn(rs); ResultSet rs1 = MusicCore.get(preparedQueryObject); assertNotNull(rs1); @@ -414,6 +459,8 @@ public class TestMusicCore { preparedQueryObject = Mockito.mock(PreparedQueryObject.class); MusicLockState musicLockState = new MusicLockState(LockStatus.UNLOCKED, "id1"); rs = Mockito.mock(ResultSet.class); + session = Mockito.mock(Session.class); + Mockito.when(mDstoreHandle.getSession()).thenReturn(session); Mockito.when(mLockHandle.getLockState("ks1" + "." + "tn1" + "." + "pk1")) .thenReturn(musicLockState); Mockito.when(mDstoreHandle.executeCriticalGet(preparedQueryObject)).thenReturn(rs); diff --git a/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java b/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java new file mode 100644 index 00000000..823badaa --- /dev/null +++ b/src/test/java/org/onap/music/unittests/TestMusicCoreIntegration.java @@ -0,0 +1,176 @@ +/* + * ============LICENSE_START========================================== org.onap.music + * =================================================================== Copyright (c) 2017 AT&T + * Intellectual Property =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.util.List; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.exceptions.MusicQueryException; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.lockingservice.MusicLockState; +import org.onap.music.lockingservice.MusicLockingService; +import org.onap.music.lockingservice.MusicLockState.LockStatus; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.main.ResultType; +import org.onap.music.main.ReturnType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestMusicCoreIntegration { + + static TestingServer zkServer; + static PreparedQueryObject testObject; + static String lockId = null; + static String lockName = "ks1.tb1.pk1"; + + @BeforeClass + public static void init() throws Exception { + try { + MusicCore.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); + zkServer = new TestingServer(2181, new File("/tmp/zk")); + MusicCore.mLockHandle = new MusicLockingService(); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("####Port:" + zkServer.getPort()); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + System.out.println("After class"); + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.dropKeyspace); + MusicCore.eventualPut(testObject); + MusicCore.deleteLock(lockName); + MusicCore.mDstoreHandle.close(); + MusicCore.mLockHandle.getzkLockHandle().close(); + MusicCore.mLockHandle.close(); + zkServer.stop(); + + } + + @Test + public void Test1_SetUp() throws MusicServiceException, MusicQueryException { + MusicCore.mLockHandle = new MusicLockingService(); + boolean result = false; + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createKeySpace); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString(CassandraCQL.createTableEmployees); + result = MusicCore.nonKeyRelatedPut(testObject, MusicUtil.EVENTUAL); + assertTrue(result); + } + + @Test + public void Test2_atomicPut() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedInsertQueryObject1(); + ReturnType returnType = MusicCore.atomicPut("testCassa", "employees", "Mr Test one", + testObject, null); + assertEquals(ResultType.SUCCESS, returnType.getResult()); + } + + @Test + public void Test3_atomicPutWithDeleteLock() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedInsertQueryObject2(); + ReturnType returnType = MusicCore.atomicPutWithDeleteLock("testCassa", "employees", + "Mr Test two", testObject, null); + assertEquals(ResultType.SUCCESS, returnType.getResult()); + } + + @Test + public void Test4_atomicGetWithDeleteLock() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedGetQuery(); + ResultSet resultSet = MusicCore.atomicGetWithDeleteLock("testCassa", "employees", + "Mr Test one", testObject); + List<Row> rows = resultSet.all(); + assertEquals(1, rows.size()); + } + + @Test + public void Test5_atomicGet() throws Exception { + testObject = new PreparedQueryObject(); + testObject = CassandraCQL.setPreparedGetQuery(); + ResultSet resultSet = + MusicCore.atomicGet("testCassa", "employees", "Mr Test two", testObject); + List<Row> rows = resultSet.all(); + assertEquals(1, rows.size()); + } + + @Test + public void Test6_createLockReference() throws Exception { + lockId = MusicCore.createLockReference(lockName); + assertNotNull(lockId); + } + + @Test + public void Test7_acquireLockwithLease() throws Exception { + ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, 1000); + assertEquals(ResultType.SUCCESS, lockLeaseStatus.getResult()); + } + + @Test + public void Test8_acquireLock() throws Exception { + ReturnType lockStatus = MusicCore.acquireLock(lockName, lockId); + assertEquals(ResultType.SUCCESS, lockStatus.getResult()); + } + + @Test + public void Test9_release() throws Exception { + MusicLockState musicLockState = new MusicLockState(LockStatus.LOCKED, "id1"); + MusicLockState musicLockState1 = new MusicLockState(LockStatus.UNLOCKED, "id1"); + MusicCore.whoseTurnIsIt(lockName); + MusicLockState mls = MusicCore.getMusicLockState(lockName); + boolean voluntaryRelease = true; + MusicLockState mls1 = MusicCore.releaseLock(lockId, voluntaryRelease); + assertEquals(musicLockState.getLockStatus(), mls.getLockStatus()); + assertEquals(musicLockState1.getLockStatus(), mls1.getLockStatus()); + } + + @Test + public void Test10_create() { + MusicCore.pureZkCreate("/nodeName"); + } + + @Test + public void Test11_write() { + MusicCore.pureZkWrite("nodeName", "I'm Test".getBytes()); + } + + @Test + public void Test12_read() { + byte[] data = MusicCore.pureZkRead("nodeName"); + String data1 = new String(data); + assertEquals("I'm Test", data1); + } + +} diff --git a/src/test/java/org/onap/music/unittests/TestRestMusicData.java b/src/test/java/org/onap/music/unittests/TestRestMusicData.java new file mode 100644 index 00000000..e4d06f70 --- /dev/null +++ b/src/test/java/org/onap/music/unittests/TestRestMusicData.java @@ -0,0 +1,450 @@ +/* + * ============LICENSE_START========================================== org.onap.music + * =================================================================== Copyright (c) 2017 AT&T + * Intellectual Property =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests; + +import static org.junit.Assert.assertEquals; +import static org.onap.music.main.MusicCore.mLockHandle; +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import org.apache.curator.test.TestingServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.datastore.jsonobjects.JsonDelete; +import org.onap.music.datastore.jsonobjects.JsonInsert; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; +import org.onap.music.datastore.jsonobjects.JsonOnboard; +import org.onap.music.datastore.jsonobjects.JsonSelect; +import org.onap.music.datastore.jsonobjects.JsonTable; +import org.onap.music.datastore.jsonobjects.JsonUpdate; +import org.onap.music.lockingservice.MusicLockingService; +import org.onap.music.main.CachingUtil; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import org.onap.music.rest.RestMusicAdminAPI; +import org.onap.music.rest.RestMusicDataAPI; +import org.onap.music.rest.RestMusicLocksAPI; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(MockitoJUnitRunner.class) +public class TestRestMusicData { + + RestMusicDataAPI data = new RestMusicDataAPI(); + RestMusicAdminAPI admin = new RestMusicAdminAPI(); + RestMusicLocksAPI lock = new RestMusicLocksAPI(); + static PreparedQueryObject testObject; + static TestingServer zkServer; + + @Mock + HttpServletResponse http; + + @Mock + UriInfo info; + + static String appName = "TestApp"; + static String userId = "TestUser"; + static String password = "TestPassword"; + static boolean isAAF = false; + static UUID uuid = UUID.fromString("abc66ccc-d857-4e90-b1e5-df98a3d40ce6"); + static String keyspaceName = "testCassa"; + static String tableName = "employees"; + static String xLatestVersion = "X-latestVersion"; + static String onboardUUID = null; + static String lockId = null; + static String lockName = "testCassa.employees.sample3"; + + @BeforeClass + public static void init() throws Exception { + try { + MusicCore.mDstoreHandle = CassandraCQL.connectToEmbeddedCassandra(); + zkServer = new TestingServer(2181, new File(" mp/zk")); + MusicCore.mLockHandle = new MusicLockingService(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + System.out.println("After class"); + testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS " + keyspaceName); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString("DROP KEYSPACE IF EXISTS admin"); + MusicCore.eventualPut(testObject); + MusicCore.mDstoreHandle.close(); + MusicCore.mLockHandle.getzkLockHandle().close(); + MusicCore.mLockHandle.close(); + zkServer.stop(); + } + + @Test + public void Test1_createKeyspace() throws Exception { + testObject = new PreparedQueryObject(); + testObject.appendQueryString("CREATE KEYSPACE admin WITH REPLICATION = " + + "{'class' : 'SimpleStrategy' , " + + "'replication_factor': 1} AND DURABLE_WRITES = true"); + MusicCore.eventualPut(testObject); + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "CREATE TABLE admin.keyspace_master (" + " uuid uuid, keyspace_name text," + + " application_name text, is_api boolean," + + " password text, username text," + + " is_aaf boolean, PRIMARY KEY (uuid)\n" + ");"); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "INSERT INTO admin.keyspace_master (uuid, keyspace_name, application_name, is_api, " + + "password, username, is_aaf) VALUES (?,?,?,?,?,?,?)"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), + UUID.fromString("bbc66ccc-d857-4e90-b1e5-df98a3d40de6"))); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), "TestApp1")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), password)); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), "TestUser1")); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF)); + MusicCore.eventualPut(testObject); + + testObject = new PreparedQueryObject(); + testObject.appendQueryString( + "select uuid from admin.keyspace_master where application_name = ? allow filtering"); + testObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName)); + ResultSet rs = MusicCore.get(testObject); + List<Row> rows = rs.all(); + if (rows.size() > 0) { + System.out.println("#######UUID is:" + rows.get(0).getUUID("uuid")); + } + } + + @Test + public void Test2_createKeyspace() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName(keyspaceName); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.createKeySpace("1", "1", "1", null, appName, userId, + password, jsonKeyspace, keyspaceName, http); + assertEquals(uuid.toString(), resultMap.get("aid")); + } + + @Test + public void Test3_createKeyspace1() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName("TestApp1"); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.createKeySpace("1", "1", "1", null, "TestApp1", + "TestUser1", password, jsonKeyspace, keyspaceName, http); + System.out.println("#######status is " + resultMap.get("Exception")); + assertEquals("Couldn't create keyspace. Please make sure all the information is correct.", + resultMap.get("Exception")); + } + + @Test + public void Test3_createTable() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, String> fields = new HashMap<>(); + fields.put("uuid", "text"); + fields.put("emp_name", "text"); + fields.put("emp_salary", "varint"); + fields.put("PRIMARY KEY", "(emp_name)"); + consistencyInfo.put("type", "eventual"); + jsonTable.setConsistencyInfo(consistencyInfo); + jsonTable.setKeyspaceName(keyspaceName); + jsonTable.setPrimaryKey("emp_name"); + jsonTable.setTableName(tableName); + jsonTable.setFields(fields); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.createTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonTable, keyspaceName, tableName, http); + assertEquals("SUCCESS", resultMap.get("status")); + } + + @Test + public void Test4_insertIntoTable() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "testName"); + values.put("emp_salary", 500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.insertIntoTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, jsonInsert, keyspaceName, tableName, http); + assertEquals("Success", resultMap.get("result")); + } + + @Test + public void Test4_insertIntoTable2() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> values = new HashMap<>(); + values.put("uuid", "cfd66ccc-d857-4e90-b1e5-df98a3d40cd6"); + values.put("emp_name", "test1"); + values.put("emp_salary", 1500); + consistencyInfo.put("type", "eventual"); + jsonInsert.setConsistencyInfo(consistencyInfo); + jsonInsert.setKeyspaceName(keyspaceName); + jsonInsert.setTableName(tableName); + jsonInsert.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.insertIntoTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonInsert, keyspaceName, tableName, http); + assertEquals("Success", resultMap.get("result")); + } + + @Test + public void Test5_updateTable() throws Exception { + JsonUpdate jsonUpdate = new JsonUpdate(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + Map<String, Object> values = new HashMap<>(); + row.add("emp_name", "testName"); + values.put("emp_salary", 2500); + consistencyInfo.put("type", "atomic"); + jsonUpdate.setConsistencyInfo(consistencyInfo); + jsonUpdate.setKeyspaceName(keyspaceName); + jsonUpdate.setTableName(tableName); + jsonUpdate.setValues(values); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Map<String, Object> resultMap = data.updateTable("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, + userId, password, jsonUpdate, keyspaceName, tableName, info, http); + assertEquals("Success", resultMap.get("result")); + } + + @Test + public void Test6_select() throws Exception { + JsonSelect jsonSelect = new JsonSelect(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "testName"); + consistencyInfo.put("type", "atomic"); + jsonSelect.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Map<String, HashMap<String, Object>> resultMap = data.select("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, keyspaceName, tableName, info, http); + assertEquals("2500", resultMap.get("row 0").get("emp_salary").toString()); + } + + @Test + public void Test6_selectCritical() throws Exception { + JsonInsert jsonInsert = new JsonInsert(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "testName"); + consistencyInfo.put("type", "atomic"); + jsonInsert.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Map<String, HashMap<String, Object>> resultMap = data.selectCritical("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, jsonInsert, keyspaceName, tableName, + info, http); + assertEquals("2500", resultMap.get("row 0").get("emp_salary").toString()); + } + + @Test + public void Test6_deleteFromTable() throws Exception { + JsonDelete jsonDelete = new JsonDelete(); + Map<String, String> consistencyInfo = new HashMap<>(); + MultivaluedMap<String, String> row = new MultivaluedMapImpl(); + row.add("emp_name", "test1"); + consistencyInfo.put("type", "atomic"); + jsonDelete.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Mockito.when(info.getQueryParameters()).thenReturn(row); + Map<String, Object> resultMap = data.deleteFromTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonDelete, keyspaceName, tableName, info, http); + assertEquals("Success", resultMap.get("result")); + } + + @Test + public void Test7_dropTable() throws Exception { + JsonTable jsonTable = new JsonTable(); + Map<String, String> consistencyInfo = new HashMap<>(); + consistencyInfo.put("type", "atomic"); + jsonTable.setConsistencyInfo(consistencyInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.dropTable("1", "1", "1", + "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", appName, userId, password, + jsonTable, keyspaceName, tableName, http); + assertEquals("SUCCESS", resultMap.get("status")); + } + + @Test + public void Test8_deleteKeyspace() throws Exception { + JsonKeySpace jsonKeyspace = new JsonKeySpace(); + Map<String, String> consistencyInfo = new HashMap<>(); + Map<String, Object> replicationInfo = new HashMap<>(); + consistencyInfo.put("type", "eventual"); + replicationInfo.put("class", "SimpleStrategy"); + replicationInfo.put("replication_factor", 1); + jsonKeyspace.setConsistencyInfo(consistencyInfo); + jsonKeyspace.setDurabilityOfWrites("true"); + jsonKeyspace.setKeyspaceName("TestApp1"); + jsonKeyspace.setReplicationInfo(replicationInfo); + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = data.dropKeySpace("1", "1", "1", "abc66ccc-d857-4e90-b1e5-df98a3d40ce6", + appName, userId, password, jsonKeyspace, keyspaceName, http); + assertEquals("SUCCESS", resultMap.get("status")); + } + + @Test + public void Test6_onboard() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser2"); + jsonOnboard.setPassword("TestPassword2"); + Map<String, Object> resultMap = admin.onboardAppWithMusic(jsonOnboard, http); + resultMap.containsKey("success"); + onboardUUID = resultMap.get("Generated AID").toString(); + assertEquals("Your application TestApp2 has been onboarded with MUSIC.", resultMap.get("Success")); + } + + @Test + public void Test7_onboardSearch() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = admin.getOnboardedInfoSearch(jsonOnboard, http); + resultMap.containsKey("success"); + assertEquals(MusicUtil.DEFAULTKEYSPACENAME, resultMap.get(onboardUUID)); + + } + + @Test + public void Test8_onboardUpdate() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setIsAAF("false"); + jsonOnboard.setUserId("TestUser3"); + jsonOnboard.setPassword("TestPassword3"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = admin.updateOnboardApp(jsonOnboard, http); + resultMap.containsKey("success"); + assertEquals("Your application has been updated successfully", resultMap.get("Success")); + } + + @Test + public void Test9_onboardDelete() throws Exception { + JsonOnboard jsonOnboard = new JsonOnboard(); + jsonOnboard.setAppname("TestApp2"); + jsonOnboard.setAid(onboardUUID); + Map<String, Object> resultMap = admin.deleteOnboardApp(jsonOnboard, http); + resultMap.containsKey("success"); + assertEquals("Your application has been deleted successfully", resultMap.get("Success")); + } + + @Test + public void Test3_createLockReference() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = lock.createLockReference(lockName, uuid.toString(), appName, null, null, http); + @SuppressWarnings("unchecked") + Map<String, Object> resultMap1 = (Map<String, Object>) resultMap.get("lock"); + lockId = (String) resultMap1.get("lock"); + assertEquals("SUCCESS", resultMap.get("status").toString()); + } + + @Test + public void Test4_accquireLock() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = lock.accquireLock(lockId, uuid.toString(), appName, null, null, http); + assertEquals("SUCCESS", resultMap.get("status").toString()); + } + + @Test + public void Test5_currentLockHolder() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = lock.currentLockHolder(lockName, uuid.toString(), appName, null, null, http); + assertEquals("SUCCESS", resultMap.get("status").toString()); + } + + @Test + public void Test7_unLock() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = lock.unLock(lockId, uuid.toString(), appName, null, null, http); + assertEquals("SUCCESS", resultMap.get("status").toString()); + } + + @Test + public void Test8_delete() throws Exception { + Mockito.doNothing().when(http).addHeader(xLatestVersion, MusicUtil.getVersion()); + Map<String, Object> resultMap = lock.deleteLock(lockName, uuid.toString(), appName, null, null, http); + assertEquals("SUCCESS", resultMap.get("status").toString()); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java new file mode 100644 index 00000000..354668c7 --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/AAFResponseTest.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.ArrayList; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.AAFResponse; +import org.onap.music.datastore.jsonobjects.NameSpace; + +public class AAFResponseTest { + + @Test + public void testGetNs() { + NameSpace ns = new NameSpace(); + AAFResponse ar = new AAFResponse(); + ArrayList<NameSpace> nsArray = new ArrayList<>(); + ns.setName("tom"); + ArrayList<String> admin = new ArrayList<>(); + admin.add("admin1"); + ns.setAdmin(admin); + nsArray.add(ns); + ar.setNs(nsArray); + assertEquals("tom",ar.getNs().get(0).getName()); + assertEquals("admin1",ar.getNs().get(0).getAdmin().get(0)); + + } + +// @Test +// public void testSetNs() { +// fail("Not yet implemented"); +// } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java new file mode 100644 index 00000000..885694bd --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonDeleteTest.java @@ -0,0 +1,86 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonDelete; + +public class JsonDeleteTest { + + JsonDelete jd = null; + + @Before + public void init() { + jd = new JsonDelete(); + } + + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + jd.setConditions(mapSo); + assertEquals("one",jd.getConditions().get("key1")); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> mapSs = new HashMap<>(); + mapSs = new HashMap<>(); + mapSs.put("key3","three"); + mapSs.put("key4","four"); + jd.setConsistencyInfo(mapSs); + assertEquals("three",jd.getConsistencyInfo().get("key3")); + } + + @Test + public void testGetColumns() { + ArrayList<String> ary = new ArrayList<>(); + ary = new ArrayList<>(); + ary.add("e1"); + ary.add("e2"); + ary.add("e3"); + jd.setColumns(ary); + assertEquals("e1",jd.getColumns().get(0)); + } + + @Test + public void testGetTtl() { + jd.setTtl("2000"); + assertEquals("2000",jd.getTtl()); + } + + @Test + public void testGetTimestamp() { + jd.setTimestamp("20:00"); + assertEquals("20:00",jd.getTimestamp()); + + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java new file mode 100644 index 00000000..69403cc7 --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonInsertTest.java @@ -0,0 +1,86 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonInsert; + +public class JsonInsertTest { + + JsonInsert ji = new JsonInsert(); + + @Test + public void testGetKeyspaceName() { + ji.setKeyspaceName("keyspace"); + assertEquals("keyspace",ji.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + ji.setTableName("table"); + assertEquals("table",ji.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String,String> cons = new HashMap<>(); + cons.put("test","true"); + ji.setConsistencyInfo(cons); + assertEquals("true",ji.getConsistencyInfo().get("test")); + } + + @Test + public void testGetTtl() { + ji.setTtl("ttl"); + assertEquals("ttl",ji.getTtl()); + } + + @Test + public void testGetTimestamp() { + ji.setTimestamp("10:30"); + assertEquals("10:30",ji.getTimestamp()); + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setValues(cons); + assertEquals("one",ji.getValues().get("val1")); + } + + @Test + public void testGetRow_specification() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ji.setRow_specification(cons); + assertEquals("two",ji.getRow_specification().get("val2")); + } + + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java new file mode 100644 index 00000000..882d5d5e --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonKeySpaceTest.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonKeySpace; + +public class JsonKeySpaceTest { + + JsonKeySpace jk = null; + + + @Before + public void init() { + jk = new JsonKeySpace(); + } + + + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jk.setConsistencyInfo(mapSs); + assertEquals("one",jk.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetReplicationInfo() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("k1", "one"); + jk.setReplicationInfo(mapSo); + assertEquals("one",jk.getReplicationInfo().get("k1")); + + } + + @Test + public void testGetDurabilityOfWrites() { + jk.setDurabilityOfWrites("1"); + assertEquals("1",jk.getDurabilityOfWrites()); + } + + @Test + public void testGetKeyspaceName() { + jk.setKeyspaceName("Keyspace"); + assertEquals("Keyspace",jk.getKeyspaceName()); + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java new file mode 100644 index 00000000..63f901c6 --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonLeasedLockTest.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonLeasedLock; + +public class JsonLeasedLockTest { + + JsonLeasedLock jl = null; + + @Before + public void init() { + jl = new JsonLeasedLock(); + } + + + @Test + public void testGetLeasePeriod() { + long lease = 20000; + jl.setLeasePeriod(lease); + assertEquals(lease,jl.getLeasePeriod()); + } + + @Test + public void testGetNotifyUrl() { + String url = "http://somewhere.com"; + jl.setNotifyUrl(url); + assertEquals(url,jl.getNotifyUrl()); + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java new file mode 100644 index 00000000..82f1748a --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonOnboardTest.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonOnboard; + +public class JsonOnboardTest { + + JsonOnboard jo = null; + + @Before + public void init() { + jo = new JsonOnboard(); + } + + + @Test + public void testGetPassword() { + String password = "password"; + jo.setPassword(password); + assertEquals(password,jo.getPassword()); + } + + @Test + public void testGetAid() { + String aid = "aid"; + jo.setAid(aid); + assertEquals(aid,jo.getAid()); + + } + + @Test + public void testGetAppname() { + String appName = "appName"; + jo.setAppname(appName); + assertEquals(appName,jo.getAppname()); + + } + + @Test + public void testGetUserId() { + String userId = "userId"; + jo.setUserId(userId); + assertEquals(userId,jo.getUserId()); + + } + + @Test + public void testGetIsAAF() { + String aaf = "true"; + jo.setIsAAF(aaf); + assertEquals(aaf,jo.getIsAAF()); + + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java new file mode 100644 index 00000000..0243232f --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonSelectTest.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonSelect; + +public class JsonSelectTest { + + @Test + public void testGetConsistencyInfo() { + JsonSelect js = new JsonSelect(); + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + js.setConsistencyInfo(mapSs); + assertEquals("one",js.getConsistencyInfo().get("k1")); + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java new file mode 100644 index 00000000..e4c800fc --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonTableTest.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonTable; + +public class JsonTableTest { + + JsonTable jt = null; + + @Before + public void init() { + jt = new JsonTable(); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + jt.setConsistencyInfo(mapSs); + assertEquals("one",jt.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetProperties() { + Map<String, Object> properties = new HashMap<>(); + properties.put("k1", "one"); + jt.setProperties(properties); + } + + @Test + public void testGetFields() { + Map<String, String> fields = new HashMap<>(); + fields.put("k1", "one"); + jt.setFields(fields); + assertEquals("one",jt.getFields().get("k1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + jt.setKeyspaceName(keyspace); + assertEquals(keyspace,jt.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + jt.setTableName(table); + assertEquals(table,jt.getTableName()); + } + + @Test + public void testGetSortingKey() { + String sortKey = "sortkey"; + jt.setSortingKey(sortKey); + assertEquals(sortKey,jt.getSortingKey()); + } + + @Test + public void testGetClusteringOrder() { + String clusteringOrder = "clusteringOrder"; + jt.setClusteringOrder(clusteringOrder); + assertEquals(clusteringOrder,jt.getClusteringOrder()); + } + + @Test + public void testGetPrimaryKey() { + String primaryKey = "primaryKey"; + jt.setPrimaryKey(primaryKey); + assertEquals(primaryKey,jt.getPrimaryKey()); + } + +} diff --git a/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java b/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java new file mode 100644 index 00000000..54db0540 --- /dev/null +++ b/src/test/java/org/onap/music/unittests/jsonobjects/JsonUpdateTest.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2018 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + *******************************************************************************/ +package org.onap.music.unittests.jsonobjects; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.onap.music.datastore.jsonobjects.JsonUpdate; + +public class JsonUpdateTest { + + JsonUpdate ju = null; + + @Before + public void init() { + ju = new JsonUpdate(); + } + + + @Test + public void testGetConditions() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setConditions(mapSo); + assertEquals("one",ju.getConditions().get("key1")); + } + + @Test + public void testGetRow_specification() { + Map<String,Object> mapSo = new HashMap<>(); + mapSo.put("key1","one"); + mapSo.put("key2","two"); + ju.setRow_specification(mapSo); + assertEquals("one",ju.getRow_specification().get("key1")); + } + + @Test + public void testGetKeyspaceName() { + String keyspace = "keyspace"; + ju.setKeyspaceName(keyspace); + assertEquals(keyspace,ju.getKeyspaceName()); + } + + @Test + public void testGetTableName() { + String table = "table"; + ju.setTableName(table); + assertEquals(table,ju.getTableName()); + } + + @Test + public void testGetConsistencyInfo() { + Map<String, String> mapSs = new HashMap<>(); + mapSs.put("k1", "one"); + ju.setConsistencyInfo(mapSs); + assertEquals("one",ju.getConsistencyInfo().get("k1")); + } + + @Test + public void testGetTtl() { + ju.setTtl("2000"); + assertEquals("2000",ju.getTtl()); + } + + @Test + public void testGetTimestamp() { + ju.setTimestamp("20:00"); + assertEquals("20:00",ju.getTimestamp()); + + } + + @Test + public void testGetValues() { + Map<String,Object> cons = new HashMap<>(); + cons.put("val1","one"); + cons.put("val2","two"); + ju.setValues(cons); + assertEquals("one",ju.getValues().get("val1")); + } + +} diff --git a/version.properties b/version.properties index f4a16a7a..632fc91b 100644 --- a/version.properties +++ b/version.properties @@ -4,7 +4,7 @@ major=2 minor=4 -patch=12 +patch=15 base_version=${major}.${minor}.${patch} |