Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
77843631
Commit
77843631
authored
May 19, 2016
by
Razvan Becheriu
Committed by
Tomek Mrugalski
Jun 23, 2016
Browse files
added support for datastax cassandra
parent
53c1c6aa
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
src/bin/admin/tests/data/dscsql.lease4_dump_test.reference.csv
0 → 100644
View file @
77843631
address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname
0.0.0.10,3230,3330,40,2015-01-01 01:15:30,50,1,1,one.example.com
0.0.0.11,,313233,40,2015-02-02 02:30:45,50,1,1,
0.0.0.12,3232,,40,2015-03-03 11:01:07,50,1,1,three.example.com
src/bin/admin/tests/data/dscsql.lease6_dump_test.reference.csv
0 → 100644
View file @
77843631
address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source
10,3230,30,2015-04-04 01:15:30,40,50,IA_TA,60,70,1,1,one.example.com,3830,90,100
11,,30,2015-05-05 02:30:45,40,50,IA_TA,60,70,1,1,,3830,90,100
12,3231,30,2015-06-06 11:01:07,40,50,IA_TA,60,70,1,1,three.example.com,3830,90,100
src/bin/admin/tests/dhcpdb_create_1.0.cql
0 → 100644
View file @
77843631
-- Copyright (C) 2015 - 2016 Deutsche Telekom AG.
-- Author: Razvan Becheriu <razvan.becheriu@qualitance.com>
-- 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.
-- This is the Kea schema 1.0 specification for DataStax Cassandra SQL.
-- Note: this is outdated version on purpose and it used to test upgrade
-- process. Do not update this file to 2.0 or any later.
-- The schema is reasonably portable (with the exception of the engine
-- specification, which is Datastax Cassandra SQL-specific). Minor changes might be needed for
-- other databases.
-- To create the schema, either type the command:
-- cqlsh -u <user> -p <password> -k <database> -f dhcpdb_create.cql
-- ... at the command prompt, or log in to the DSC SQL database and at the "cqlsh>"
-- prompt, issue the command:
-- SOURCE dhcpdb_create.cql
-- This script is also called from kea-admin, see kea-admin init dscsql
-- Over time, Kea database schema will evolve. Each version is marked with
-- major.minor version. This file is organized sequentially, i.e. database
-- is initialized to 1.0, then upgraded to 2.0 etc. This may be somewhat
-- sub-optimal, but it ensues consistency with upgrade scripts. (It is much
-- easier to maintain init and upgrade scripts if they look the same).
-- Since initialization is done only once, it's perfromance is not an issue.
-- This line starts database initialization to 1.0.
-- Holds the IPv4 leases.
CREATE TABLE lease4 (
address int,
hwaddr blob,
client_id blob,
valid_lifetime bigint,
expire bigint,
subnet_id int,
fqdn_fwd boolean,
fqdn_rev boolean,
hostname varchar,
state int,
PRIMARY KEY (address)
);
-- Create search indexes for lease4 table
CREATE INDEX lease4index1 ON lease4 (client_id);
CREATE INDEX lease4index2 ON lease4 (subnet_id);
CREATE INDEX lease4index3 ON lease4 (hwaddr);
CREATE INDEX lease4index4 ON lease4 (state);
-- Holds the IPv6 leases.
-- N.B. The use of a VARCHAR for the address is temporary for development:
-- it will eventually be replaced by BINARY(16).
CREATE TABLE lease6 (
address varchar,
duid blob,
valid_lifetime bigint,
expire bigint,
subnet_id int,
pref_lifetime bigint,
lease_type int,
iaid int,
prefix_len int,
fqdn_fwd boolean,
fqdn_rev boolean,
hostname varchar,
hwaddr blob,
hwtype int,
hwaddr_source int,
state int,
PRIMARY KEY (address)
);
-- Create search indexes for lease6 table
CREATE INDEX lease6index1 ON lease6 (lease_type);
CREATE INDEX lease6index2 ON lease6 (duid);
CREATE INDEX lease6index3 ON lease6 (iaid);
CREATE INDEX lease6index4 ON lease6 (subnet_id);
CREATE INDEX lease6index5 ON lease6 (state);
-- ... and a definition of lease6 types. This table is a convenience for
-- users of the database - if they want to view the lease table and use the
-- type names, they can join this table with the lease6 table.
-- Make sure those values match Lease6::LeaseType enum (see src/bin/dhcpsrv/
-- lease_mgr.h)
CREATE TABLE lease6_types (
lease_type int, -- Lease type code.
name varchar, -- Name of the lease type
PRIMARY KEY (lease_type)
);
--START TRANSACTION;
INSERT INTO lease6_types (lease_type, name) VALUES (0, 'IA_NA'); -- Non-temporary v6 addresses
INSERT INTO lease6_types (lease_type, name) VALUES (1, 'IA_TA'); -- Temporary v6 addresses
INSERT INTO lease6_types (lease_type, name) VALUES (2, 'IA_PD'); -- Prefix delegations
--COMMIT;
-- Kea keeps track of the hardware/MAC address source, i.e. how the address
-- was obtained. Depending on the technique and your network topology, it may
-- be more or less trustworthy. This table is a convenience for
-- users of the database - if they want to view the lease table and use the
-- type names, they can join this table with the lease6 table. For details,
-- see constants defined in src/lib/dhcp/dhcp/pkt.h for detailed explanation.
CREATE TABLE lease_hwaddr_source (
hwaddr_source int,
name varchar,
PRIMARY KEY (hwaddr_source)
);
-- Hardware address obtained from raw sockets
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (1, 'HWADDR_SOURCE_RAW');
-- Hardware address converted from IPv6 link-local address with EUI-64
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (2, 'HWADDR_SOURCE_IPV6_LINK_LOCAL');
-- Hardware address extracted from client-id (duid)
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (4, 'HWADDR_SOURCE_DUID');
-- Hardware address extracted from client address relay option (RFC6939)
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (8, 'HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION');
-- Hardware address extracted from remote-id option (RFC4649)
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (16, 'HWADDR_SOURCE_REMOTE_ID');
-- Hardware address extracted from subscriber-id option (RFC4580)
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (32, 'HWADDR_SOURCE_SUBSCRIBER_ID');
-- Hardware address extracted from docsis options
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (64, 'HWADDR_SOURCE_DOCSIS_CMTS');
-- -----------------------------------------------------
-- Table `dhcp4_options`
-- -----------------------------------------------------
CREATE TABLE dhcp4_options (
option_id int,
code int,
value blob,
formatted_value varchar,
space varchar,
persistent int,
dhcp_client_class varchar,
dhcp4_subnet_id int,
host_id int,
PRIMARY KEY (option_id)
);
-- Create search indexes for dhcp4_options table
CREATE INDEX dhcp4_optionsindex1 ON dhcp4_options (host_id);
-- -----------------------------------------------------
-- Table `dhcp6_options`
-- -----------------------------------------------------
CREATE TABLE dhcp6_options (
option_id int,
code int,
value blob,
formatted_value varchar,
space varchar,
persistent int,
dhcp_client_class varchar,
dhcp6_subnet_id int,
host_id int,
PRIMARY KEY (option_id)
);
-- Create search indexes for dhcp6_options table
CREATE INDEX dhcp6_optionsindex1 ON dhcp6_options (host_id);
-- Create table holding mapping of the lease states to their names.
-- This is not used in queries from the DHCP server but rather in
-- direct queries from the lease database management tools.
CREATE TABLE lease_state (
state int,
name varchar,
PRIMARY KEY (state)
);
-- Insert currently defined state names.
INSERT INTO lease_state (state, name) VALUES (0, 'default');
INSERT INTO lease_state (state, name) VALUES (1, 'declined');
INSERT INTO lease_state (state, name) VALUES (2, 'expired-reclaimed');
-- Finally, the version of the schema. We start at 1.0 during development.
-- This table is only modified during schema upgrades. For historical reasons
-- (related to the names of the columns in the BIND 10 DNS database file), the
-- first column is called "version" and not "major".
-- NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
-- which defines the schema for the unit tests. If you are updating
-- the version number, the schema has changed: please ensure that
-- schema_copy.h has been updated as well.
CREATE TABLE schema_version (
version int,
minor int,
PRIMARY KEY (version)
);
--START TRANSACTION;
INSERT INTO schema_version (version, minor) VALUES (1, 0);
--COMMIT;
src/bin/admin/tests/dscsql_tests.sh.in
0 → 100644
View file @
77843631
#!/bin/sh
# Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Include common test library.
.
@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
dscsql_init_test
()
{
test_start
"dscsql.init"
# @todo: Implement this
test_finish 0
}
dscsql_version_test
()
{
test_start
"dscsql.version"
# @todo: Implement this
test_finish 0
}
dscsql_upgrade_test
()
{
test_start
"dscsql.upgrade"
# @todo: Implement this
test_finish 0
}
dscsql_init_test
dscsql_version_test
dscsql_upgrade_test
src/lib/dhcpsrv/dscsql_connection.cc
0 → 100644
View file @
77843631
// Copyright (C) 2015 - 2016 Deutsche Telekom AG.
//
// Author: Razvan Becheriu <razvan.becheriu@qualitance.com>
//
// 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.
#include
<dhcpsrv/dscsql_connection.h>
#include
<string>
using
namespace
std
;
namespace
isc
{
namespace
dhcp
{
DSCSqlConnection
::
DSCSqlConnection
(
const
ParameterMap
&
parameters
)
:
DatabaseConnection
(
parameters
),
cluster_
(
NULL
),
session_
(
NULL
),
tagged_statements_
(
NULL
)
{
}
DSCSqlConnection
::~
DSCSqlConnection
()
{
CassError
rc
;
for
(
int
i
=
0
;
i
<
statements_
.
size
();
i
++
)
{
if
(
statements_
[
i
])
{
cass_prepared_free
(
statements_
[
i
]);
}
statements_
[
i
]
=
NULL
;
}
CassFuture
*
close_future
=
cass_session_close
(
session_
);
cass_future_wait
(
close_future
);
std
::
string
error
;
checkStatementError
(
error
,
close_future
,
"could not close connection to DB"
);
rc
=
cass_future_error_code
(
close_future
);
cass_future_free
(
close_future
);
cass_session_free
(
session_
);
session_
=
NULL
;
cass_cluster_free
(
cluster_
);
cluster_
=
NULL
;
if
(
rc
!=
CASS_OK
)
{
isc_throw
(
DbOpenError
,
error
);
}
}
void
DSCSqlConnection
::
openDatabase
()
{
CassError
rc
;
// Set up the values of the parameters
const
char
*
contact_points
=
"127.0.0.1"
;
string
scontact_points
;
try
{
scontact_points
=
getParameter
(
"contact_points"
);
contact_points
=
scontact_points
.
c_str
();
}
catch
(...)
{
// No host. Fine, we'll use "localhost"
}
const
char
*
port
=
NULL
;
string
sport
;
try
{
sport
=
getParameter
(
"port"
);
port
=
sport
.
c_str
();
}
catch
(...)
{
// No port. Fine, we'll use "default"
}
const
char
*
user
=
NULL
;
string
suser
;
try
{
suser
=
getParameter
(
"user"
);
user
=
suser
.
c_str
();
}
catch
(...)
{
// No user. Fine, we'll use NULL
}
const
char
*
password
=
NULL
;
string
spassword
;
try
{
spassword
=
getParameter
(
"password"
);
password
=
spassword
.
c_str
();
}
catch
(...)
{
// No password. Fine, we'll use NULL
}
const
char
*
keyspace
=
"keatest"
;
string
skeyspace
;
try
{
skeyspace
=
getParameter
(
"keyspace"
);
keyspace
=
skeyspace
.
c_str
();
}
catch
(...)
{
// No database name. Fine, we'll use default 'keatest'
}
cluster_
=
cass_cluster_new
();
cass_cluster_set_contact_points
(
cluster_
,
contact_points
);
if
(
user
!=
NULL
&&
password
!=
NULL
)
{
cass_cluster_set_credentials
(
cluster_
,
user
,
password
);
}
if
(
port
!=
NULL
)
{
int
port_nr
;
try
{
port_nr
=
boost
::
lexical_cast
<
int
>
(
port
);
}
catch
(
const
std
::
exception
&
ex
)
{
isc_throw
(
DbOperationError
,
"Invalid int data: "
<<
port
<<
" : "
<<
ex
.
what
());
}
cass_cluster_set_port
(
cluster_
,
port_nr
);
}
session_
=
cass_session_new
();
CassFuture
*
connect_future
=
cass_session_connect_keyspace
(
session_
,
cluster_
,
keyspace
);
cass_future_wait
(
connect_future
);
std
::
string
error
;
checkStatementError
(
error
,
connect_future
,
"could not connect to DB"
);
rc
=
cass_future_error_code
(
connect_future
);
cass_future_free
(
connect_future
);
if
(
rc
!=
CASS_OK
)
{
cass_session_free
(
session_
);
session_
=
NULL
;
cass_cluster_free
(
cluster_
);
cluster_
=
NULL
;
isc_throw
(
DbOpenError
,
error
);
}
}
void
DSCSqlConnection
::
prepareStatements
(
DSCSqlTaggedStatement
*
statements
)
{
CassError
rc
=
CASS_OK
;
CassFuture
*
future
=
NULL
;
uint32_t
size
=
0
;
tagged_statements_
=
statements
;
for
(;
tagged_statements_
[
size
].
params_
;
size
++
);
statements_
.
resize
(
size
);
for
(
uint32_t
i
=
0
;
i
<
size
;
i
++
)
{
const
char
*
query
=
tagged_statements_
[
i
].
text_
;
future
=
cass_session_prepare
(
session_
,
query
);
cass_future_wait
(
future
);
std
::
string
error
;
checkStatementError
(
error
,
future
,
i
,
"could not prepare statement"
);
rc
=
cass_future_error_code
(
future
);
if
(
rc
!=
CASS_OK
)
{
cass_future_free
(
future
);
statements_
[
i
]
=
NULL
;
isc_throw
(
DbOperationError
,
error
);
}
else
{
statements_
[
i
]
=
cass_future_get_prepared
(
future
);
}
cass_future_free
(
future
);
}
}
string
DSCSqlConnection
::
getName
()
const
{
string
name
=
""
;
try
{
name
=
getParameter
(
"name"
);
}
catch
(...)
{
// Return an empty name
}
return
(
name
);
}
string
DSCSqlConnection
::
getDescription
()
const
{
return
(
string
(
"DataStax Cassandra Database"
));
}
pair
<
uint32_t
,
uint32_t
>
DSCSqlConnection
::
getVersion
()
const
{
LOG_DEBUG
(
dhcpsrv_logger
,
DHCPSRV_DBG_TRACE_DETAIL
,
DHCPSRV_DSCSQL_GET_VERSION
);
uint32_t
version
=
CASS_VERSION_MAJOR
;
uint32_t
minor
=
CASS_VERSION_MINOR
;
return
make_pair
<
uint32_t
,
uint32_t
>
(
version
,
minor
);
}
void
DSCSqlConnection
::
commit
()
{
LOG_DEBUG
(
dhcpsrv_logger
,
DHCPSRV_DBG_TRACE_DETAIL
,
DHCPSRV_DSCSQL_COMMIT
);
}
void
DSCSqlConnection
::
rollback
()
{
LOG_DEBUG
(
dhcpsrv_logger
,
DHCPSRV_DBG_TRACE_DETAIL
,
DHCPSRV_DSCSQL_ROLLBACK
);
}
void
DSCSqlConnection
::
checkStatementError
(
std
::
string
&
error
,
CassFuture
*
future
,
uint32_t
stindex
,
const
char
*
what
)
const
{
CassError
rc
;
const
char
*
errorMessage
;
size_t
errorMessageSize
;
std
::
stringstream
stream
;
stream
<<
"no error for: "
<<
tagged_statements_
[
stindex
].
name_
;
rc
=
cass_future_error_code
(
future
);
cass_future_error_message
(
future
,
&
errorMessage
,
&
errorMessageSize
);
if
(
rc
!=
CASS_OK
)
{
stream
.
str
(
std
::
string
());
stream
<<
what
<<
" for: "
<<
tagged_statements_
[
stindex
].
name_
<<
" reason: "
<<
errorMessage
<<
" error code: "
<<
rc
;
}
error
=
stream
.
str
();
}
void
DSCSqlConnection
::
checkStatementError
(
std
::
string
&
error
,
CassFuture
*
future
,
const
char
*
what
)
const
{
CassError
rc
;
const
char
*
errorMessage
;
size_t
errorMessageSize
;
std
::
stringstream
stream
;
stream
<<
"no error"
;
rc
=
cass_future_error_code
(
future
);
cass_future_error_message
(
future
,
&
errorMessage
,
&
errorMessageSize
);
if
(
rc
!=
CASS_OK
)
{
stream
.
str
(
std
::
string
());
stream
<<
what
<<
" reason: "
<<
errorMessage
<<
" error code: "
<<
rc
;
}
error
=
stream
.
str
();
}
};
// end of isc::dhcp namespace
};
// end of isc namespace
src/lib/dhcpsrv/dscsql_connection.h
0 → 100644
View file @
77843631
// Copyright (C) 2015 - 2016 Deutsche Telekom AG.
//
// Author: Razvan Becheriu <razvan.becheriu@qualitance.com>
//
// 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.
#ifndef DSCSQL_CONNECTION_H
#define DSCSQL_CONNECTION_H
#include
<dhcpsrv/database_connection.h>
#include
<dhcpsrv/dhcpsrv_log.h>
#include
<inttypes.h>
#include
<cassandra.h>
#include
<vector>
namespace
isc
{
namespace
dhcp
{
/// @brief Defines a single query
struct
DSCSqlTaggedStatement
{
/// Param name.
const
char
**
params_
;
/// Short name of the query.
const
char
*
name_
;
/// Text representation of the actual query.
const
char
*
text_
;
};
/// Defines DSC SQL backend version: 1.0
const
uint32_t
DSCSQL_CURRENT_VERSION
=
1
;
const
uint32_t
DSCSQL_CURRENT_MINOR
=
0
;
class
DSCSqlConnection
:
public
DatabaseConnection
{
public:
/// @brief Constructor
///
/// Initialize DSCSqlConnection object with parameters needed for connection.
DSCSqlConnection
(
const
ParameterMap
&
parameters
);
/// @brief Destructor
virtual
~
DSCSqlConnection
();
/// @brief Prepare statements
///
/// Creates the prepared statements for all of the SQL statements used
/// by the PostgreSQL backend.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
/// @throw isc::InvalidParameter 'index' is not valid for the vector. This
/// represents an internal error within the code.
void
prepareStatements
(
DSCSqlTaggedStatement
*
statements
);
/// @brief Open Database
///
/// Opens the database using the information supplied in the parameters
/// passed to the constructor.
///
/// @throw NoDatabaseName Mandatory database name not given
/// @throw DbOpenError Error opening the database
void
openDatabase
();
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
///
/// @return Type of the backend.
virtual
std
::
string
getType
()
const
{
return
(
std
::
string
(
"cassandra"
));
}
/// @brief Returns name of the database.
///
/// @return database name
virtual
std
::
string
getName
()
const
;
/// @brief Returns description of the backend.
///
/// This description may be multiline text that describes the backend.
///
/// @return Description of the backend.
virtual
std
::
string
getDescription
()
const
;
/// @brief Returns backend version.
///
/// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
virtual
std
::
pair
<
uint32_t
,
uint32_t
>
getVersion
()
const
;
/// @brief Commit Transactions
///
/// Commits all pending database operations.
///
/// @throw DbOperationError Iif the commit failed.
virtual
void
commit
();
/// @brief Rollback Transactions
///