37#include <boost/algorithm/string/classification.hpp>
38#include <boost/algorithm/string/split.hpp>
39#include <boost/assert.hpp>
40#include <boost/unordered_map.hpp>
55typedef std::vector<uint8_t> HostIdentifier;
61 tuple<HostIdentifier, Host::IdentifierType, SubnetID, SubnetID, IOAddress> HostKey;
64enum HostKeyComponent {
74typedef std::unordered_map<HostKey, HostPtr, boost::hash<HostKey>> HostMap;
77typedef std::pair<HostKey, HostPtr> HostPair;
82 : option_descriptor_(option_descriptor), option_space_(option_space) {
85 std::string option_space_;
90static constexpr size_t CLIENT_CLASSES_MAX_LENGTH = 255u;
95static constexpr size_t HOSTNAME_MAX_LENGTH = 255u;
98static constexpr size_t OPTION_VALUE_MAX_LENGTH = 4096u;
101static constexpr size_t OPTION_FORMATTED_VALUE_MAX_LENGTH = 8192u;
104static constexpr size_t OPTION_SPACE_MAX_LENGTH = 128u;
109static constexpr cass_int32_t MAX_IDENTIFIER_TYPE =
static_cast<cass_int32_t
>(
Host::IDENT_FLEX);
113static constexpr char NULL_DHCP4_SERVER_HOSTNAME[] =
"";
114static constexpr char NULL_DHCP4_BOOT_FILE_NAME[] =
"";
115static constexpr char NULL_USER_CONTEXT[] =
"";
116static constexpr char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] =
"::";
117static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0;
118static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1;
119static constexpr cass_int32_t NULL_IAID = -1;
120static constexpr cass_int32_t NULL_OPTION_UNIVERSE = -1;
121static constexpr cass_int32_t NULL_OPTION_CODE = -1;
123static constexpr char NULL_OPTION_FORMATTED_VALUE[] =
"";
124static constexpr char NULL_OPTION_SPACE[] =
"";
125static constexpr cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false;
126static constexpr char NULL_OPTION_CLIENT_CLASS[] =
"";
127static constexpr cass_int32_t NULL_OPTION_SUBNET_ID = -1;
128static constexpr char NULL_OPTION_USER_CONTEXT[] =
"";
129static constexpr cass_int32_t NULL_OPTION_SCOPE_ID = -1;
134static const IPv6Resrv NULL_IPV6_RESERVATION =
179 const std::string& option_space,
198 const std::string& option_space,
219 const std::string& option_space,
242 virtual boost::any
retrieve()
override;
274 "GET_HOST_BY_HOST_ID";
279 "GET_HOST_BY_IPV4_ADDRESS";
284 "GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID";
290 "GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID";
295 "GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS";
304 "GET_HOST_BY_IPV6_PREFIX";
309 "GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS";
333 cass_int32_t host_identifier_type_;
336 cass_int32_t host_ipv4_subnet_id_;
339 cass_int32_t host_ipv6_subnet_id_;
342 cass_int32_t host_ipv4_address_;
345 cass_int32_t host_ipv4_next_server_;
348 std::string host_ipv4_server_hostname_;
351 std::string host_ipv4_boot_file_name_;
354 std::string auth_key_;
357 std::string hostname_;
360 std::string user_context_;
363 std::string host_ipv4_client_classes_;
366 std::string host_ipv6_client_classes_;
369 std::string reserved_ipv6_prefix_address_;
372 cass_int32_t reserved_ipv6_prefix_length_;
376 cass_int32_t reserved_ipv6_prefix_address_type_;
383 cass_int32_t option_universe_;
386 cass_int32_t option_code_;
392 std::string option_formatted_value_;
395 std::string option_space_;
398 cass_bool_t option_is_persistent_;
401 std::string option_client_class_;
404 cass_int32_t option_subnet_id_;
407 std::string option_user_context_;
410 cass_int32_t option_scope_id_;
427 "INSERT INTO host_reservations ( "
430 "host_identifier_type, "
431 "host_ipv4_subnet_id, "
432 "host_ipv6_subnet_id, "
433 "host_ipv4_address, "
434 "host_ipv4_next_server, "
435 "host_ipv4_server_hostname, "
436 "host_ipv4_boot_file_name, "
440 "host_ipv4_client_classes, "
441 "host_ipv6_client_classes, "
442 "reserved_ipv6_prefix_address, "
443 "reserved_ipv6_prefix_length, "
444 "reserved_ipv6_prefix_address_type, "
449 "option_formatted_value, "
451 "option_is_persistent, "
452 "option_client_class, "
454 "option_user_context, "
460 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
462 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
472 "host_identifier_type, "
473 "host_ipv4_subnet_id, "
474 "host_ipv6_subnet_id, "
475 "host_ipv4_address, "
476 "host_ipv4_next_server, "
477 "host_ipv4_server_hostname, "
478 "host_ipv4_boot_file_name, "
482 "host_ipv4_client_classes, "
483 "host_ipv6_client_classes, "
484 "reserved_ipv6_prefix_address, "
485 "reserved_ipv6_prefix_length, "
486 "reserved_ipv6_prefix_address_type, "
491 "option_formatted_value, "
493 "option_is_persistent, "
494 "option_client_class, "
496 "option_user_context, "
498 "FROM host_reservations "
501 {GET_HOST_BY_HOST_ID,
502 {GET_HOST_BY_HOST_ID,
506 "host_identifier_type, "
507 "host_ipv4_subnet_id, "
508 "host_ipv6_subnet_id, "
509 "host_ipv4_address, "
510 "host_ipv4_next_server, "
511 "host_ipv4_server_hostname, "
512 "host_ipv4_boot_file_name, "
516 "host_ipv4_client_classes, "
517 "host_ipv6_client_classes, "
518 "reserved_ipv6_prefix_address, "
519 "reserved_ipv6_prefix_length, "
520 "reserved_ipv6_prefix_address_type, "
525 "option_formatted_value, "
527 "option_is_persistent, "
528 "option_client_class, "
530 "option_user_context, "
532 "FROM host_reservations "
533 "WHERE host_identifier = ? "
534 "AND host_identifier_type = ? "
538 {GET_HOST_BY_IPV4_ADDRESS,
539 {GET_HOST_BY_IPV4_ADDRESS,
543 "host_identifier_type, "
544 "host_ipv4_subnet_id, "
545 "host_ipv6_subnet_id, "
546 "host_ipv4_address, "
547 "host_ipv4_next_server, "
548 "host_ipv4_server_hostname, "
549 "host_ipv4_boot_file_name, "
553 "host_ipv4_client_classes, "
554 "host_ipv6_client_classes, "
555 "reserved_ipv6_prefix_address, "
556 "reserved_ipv6_prefix_length, "
557 "reserved_ipv6_prefix_address_type, "
562 "option_formatted_value, "
564 "option_is_persistent, "
565 "option_client_class, "
567 "option_user_context, "
569 "FROM host_reservations "
570 "WHERE host_ipv4_address = ? "
574 {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
575 {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
579 "host_identifier_type, "
580 "host_ipv4_subnet_id, "
581 "host_ipv6_subnet_id, "
582 "host_ipv4_address, "
583 "host_ipv4_next_server, "
584 "host_ipv4_server_hostname, "
585 "host_ipv4_boot_file_name, "
589 "host_ipv4_client_classes, "
590 "host_ipv6_client_classes, "
591 "reserved_ipv6_prefix_address, "
592 "reserved_ipv6_prefix_length, "
593 "reserved_ipv6_prefix_address_type, "
598 "option_formatted_value, "
600 "option_is_persistent, "
601 "option_client_class, "
603 "option_user_context, "
605 "FROM host_reservations "
606 "WHERE host_ipv4_subnet_id = ? "
607 "AND host_identifier = ? "
608 "AND host_identifier_type = ? "
612 {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
613 {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
617 "host_identifier_type, "
618 "host_ipv4_subnet_id, "
619 "host_ipv6_subnet_id, "
620 "host_ipv4_address, "
621 "host_ipv4_next_server, "
622 "host_ipv4_server_hostname, "
623 "host_ipv4_boot_file_name, "
627 "host_ipv4_client_classes, "
628 "host_ipv6_client_classes, "
629 "reserved_ipv6_prefix_address, "
630 "reserved_ipv6_prefix_length, "
631 "reserved_ipv6_prefix_address_type, "
636 "option_formatted_value, "
638 "option_is_persistent, "
639 "option_client_class, "
641 "option_user_context, "
643 "FROM host_reservations "
644 "WHERE host_ipv6_subnet_id = ? "
645 "AND host_identifier = ? "
646 "AND host_identifier_type = ? "
650 {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
651 {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
655 "host_identifier_type, "
656 "host_ipv4_subnet_id, "
657 "host_ipv6_subnet_id, "
658 "host_ipv4_address, "
659 "host_ipv4_next_server, "
660 "host_ipv4_server_hostname, "
661 "host_ipv4_boot_file_name, "
665 "host_ipv4_client_classes, "
666 "host_ipv6_client_classes, "
667 "reserved_ipv6_prefix_address, "
668 "reserved_ipv6_prefix_length, "
669 "reserved_ipv6_prefix_address_type, "
674 "option_formatted_value, "
676 "option_is_persistent, "
677 "option_client_class, "
679 "option_user_context, "
681 "FROM host_reservations "
682 "WHERE host_ipv4_subnet_id = ? "
683 "AND host_ipv4_address = ? "
687 {GET_HOST_BY_IPV6_PREFIX,
688 {GET_HOST_BY_IPV6_PREFIX,
692 "host_identifier_type, "
693 "host_ipv4_subnet_id, "
694 "host_ipv6_subnet_id, "
695 "host_ipv4_address, "
696 "host_ipv4_next_server, "
697 "host_ipv4_server_hostname, "
698 "host_ipv4_boot_file_name, "
702 "host_ipv4_client_classes, "
703 "host_ipv6_client_classes, "
704 "reserved_ipv6_prefix_address, "
705 "reserved_ipv6_prefix_length, "
706 "reserved_ipv6_prefix_address_type, "
711 "option_formatted_value, "
713 "option_is_persistent, "
714 "option_client_class, "
716 "option_user_context, "
718 "FROM host_reservations "
719 "WHERE reserved_ipv6_prefix_address = ? "
720 "AND reserved_ipv6_prefix_length = ? "
724 {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
725 {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
729 "host_identifier_type, "
730 "host_ipv4_subnet_id, "
731 "host_ipv6_subnet_id, "
732 "host_ipv4_address, "
733 "host_ipv4_next_server, "
734 "host_ipv4_server_hostname, "
735 "host_ipv4_boot_file_name, "
739 "host_ipv4_client_classes, "
740 "host_ipv6_client_classes, "
741 "reserved_ipv6_prefix_address, "
742 "reserved_ipv6_prefix_length, "
743 "reserved_ipv6_prefix_address_type, "
748 "option_formatted_value, "
750 "option_is_persistent, "
751 "option_client_class, "
753 "option_user_context, "
755 "FROM host_reservations "
756 "WHERE host_ipv6_subnet_id = ? "
757 "AND reserved_ipv6_prefix_address = ? "
763 "DELETE FROM host_reservations WHERE id = ? "
769 : host_(NULL), id_(0), host_identifier_type_(0), host_ipv4_subnet_id_(0),
770 host_ipv6_subnet_id_(0), host_ipv4_address_(0), host_ipv4_next_server_(0),
771 host_ipv4_server_hostname_(NULL_DHCP4_SERVER_HOSTNAME),
772 host_ipv4_boot_file_name_(NULL_DHCP4_BOOT_FILE_NAME),
774 user_context_(NULL_USER_CONTEXT),
775 reserved_ipv6_prefix_length_(NULL_RESERVED_IPV6_PREFIX_LENGTH),
776 reserved_ipv6_prefix_address_type_(NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE),
777 iaid_(NULL_IAID), option_universe_(NULL_OPTION_UNIVERSE),
778 option_code_(NULL_OPTION_CODE),
779 option_is_persistent_(NULL_OPTION_IS_PERSISTENT),
780 option_subnet_id_(NULL_OPTION_SUBNET_ID),
781 option_user_context_(NULL_OPTION_USER_CONTEXT),
782 option_scope_id_(NULL_OPTION_SCOPE_ID) {
796 data.
add(&host_identifier_);
798 data.
add(&host_identifier_type_);
800 data.
add(&host_ipv4_subnet_id_);
802 data.
add(&host_ipv6_subnet_id_);
804 data.
add(&host_ipv4_address_);
806 data.
add(&host_ipv4_next_server_);
808 data.
add(&host_ipv4_server_hostname_);
810 data.
add(&host_ipv4_boot_file_name_);
812 data.
add(&auth_key_);
814 data.
add(&hostname_);
816 data.
add(&user_context_);
818 data.
add(&host_ipv4_client_classes_);
820 data.
add(&host_ipv6_client_classes_);
824 data.
add(&reserved_ipv6_prefix_address_);
826 data.
add(&reserved_ipv6_prefix_length_);
828 data.
add(&reserved_ipv6_prefix_address_type_);
835 data.
add(&option_universe_);
837 data.
add(&option_code_);
839 data.
add(&option_value_);
841 data.
add(&option_formatted_value_);
843 data.
add(&option_space_);
845 data.
add(&option_is_persistent_);
847 data.
add(&option_client_class_);
849 data.
add(&option_subnet_id_);
851 data.
add(&option_user_context_);
853 data.
add(&option_scope_id_);
861 const std::string& option_space,
873 HostIdentifier host_identifier = host->getIdentifier();
874 host_identifier_ =
CassBlob(host_identifier.begin(), host_identifier.end());
877 << host_identifier_.data() <<
" of length " << host_identifier_.size()
882 host_identifier_type_ =
static_cast<cass_int32_t
>(host->getIdentifierType());
883 if (host_identifier_type_ > MAX_IDENTIFIER_TYPE) {
885 "host identifier type returned: " << host_identifier_type_);
889 host_ipv4_subnet_id_ =
static_cast<cass_int32_t
>(host->getIPv4SubnetID());
892 host_ipv6_subnet_id_ =
static_cast<cass_int32_t
>(host->getIPv6SubnetID());
895 host_ipv4_address_ =
static_cast<cass_int32_t
>(host->getIPv4Reservation().toUint32());
898 host_ipv4_next_server_ =
static_cast<cass_int32_t
>(host->getNextServer().toUint32());
901 host_ipv4_server_hostname_ = host->getServerHostname();
904 host_ipv4_boot_file_name_ = host->getBootFileName();
907 auth_key_ = host->getKey().ToText();
910 hostname_ = host->getHostname();
911 if (hostname_.size() > HOSTNAME_MAX_LENGTH) {
913 << hostname_ <<
" of length " << hostname_.size()
914 <<
" is greater than allowed of " << HOSTNAME_MAX_LENGTH);
920 user_context_ = ctx->str();
922 user_context_ = NULL_USER_CONTEXT;
926 host_ipv4_client_classes_ = host->getClientClasses4().toText(
",");
927 if (host_ipv4_client_classes_.size() > CLIENT_CLASSES_MAX_LENGTH) {
929 "IPv4 client classes " << host_ipv4_client_classes_ <<
" of length "
930 << host_ipv4_client_classes_.size() <<
" is greater than allowed of "
931 << CLIENT_CLASSES_MAX_LENGTH);
935 host_ipv6_client_classes_ = host->getClientClasses6().toText(
",");
936 if (host_ipv6_client_classes_.size() > CLIENT_CLASSES_MAX_LENGTH) {
938 "IPv6 client classes " << host_ipv6_client_classes_ <<
" of length "
939 << host_ipv6_client_classes_.size() <<
" is greater than allowed of "
940 << CLIENT_CLASSES_MAX_LENGTH);
943 if (reservation == NULL) {
945 reserved_ipv6_prefix_address_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS;
947 reserved_ipv6_prefix_length_ = NULL_RESERVED_IPV6_PREFIX_LENGTH;
949 reserved_ipv6_prefix_address_type_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE;
956 reserved_ipv6_prefix_length_ =
static_cast<cass_int32_t
>(reservation->
getPrefixLen());
959 reserved_ipv6_prefix_address_type_ =
967 if (option_descriptor.
option_ == NULL) {
968 option_universe_ = NULL_OPTION_UNIVERSE;
969 option_code_ = NULL_OPTION_CODE;
970 option_value_ = NULL_OPTION_VALUE;
971 option_formatted_value_ = NULL_OPTION_FORMATTED_VALUE;
972 option_space_ = NULL_OPTION_SPACE;
973 option_is_persistent_ = NULL_OPTION_IS_PERSISTENT;
974 option_client_class_ = NULL_OPTION_CLIENT_CLASS;
975 option_subnet_id_ = NULL_OPTION_SUBNET_ID;
976 option_user_context_ = NULL_OPTION_USER_CONTEXT;
977 option_scope_id_ = NULL_OPTION_SCOPE_ID;
980 option_universe_ = option_descriptor.
option_->getUniverse();
983 option_code_ = option_descriptor.
option_->getType();
988 if (option_descriptor.
option_->len() >
989 option_descriptor.
option_->getHeaderLen()) {
995 option_descriptor.
option_->pack(buffer);
996 const char* buffer_ptr =
static_cast<const char*
>(buffer.
getData());
997 option_value_.assign(buffer_ptr + option_descriptor.
option_->getHeaderLen(),
1000 option_value_.clear();
1002 option_formatted_value_.clear();
1004 option_value_.clear();
1009 option_space_ = option_space;
1012 option_is_persistent_ = option_descriptor.
persistent_ ? cass_true : cass_false;
1016 option_client_class_.clear();
1020 option_subnet_id_ = subnet_id;
1022 option_subnet_id_ = 0;
1028 option_user_context_ = ctx->str();
1030 option_user_context_ = NULL_OPTION_USER_CONTEXT;
1035 option_scope_id_ = 3;
1042 "CqlHostExchange::prepareExchange(): "
1043 "could not copy data from host "
1044 << host->getHostname() <<
", reason: " << ex.
what());
1052 const std::string& option_space,
1055 prepareExchange(host, subnet_id, reservation, option_space, option_descriptor);
1063 data.
add(&host_identifier_);
1064 data.
add(&host_identifier_type_);
1065 data.
add(&host_ipv4_subnet_id_);
1066 data.
add(&host_ipv6_subnet_id_);
1067 data.
add(&host_ipv4_address_);
1068 data.
add(&host_ipv4_next_server_);
1069 data.
add(&host_ipv4_server_hostname_);
1070 data.
add(&host_ipv4_boot_file_name_);
1071 data.
add(&auth_key_);
1072 data.
add(&hostname_);
1073 data.
add(&user_context_);
1074 data.
add(&host_ipv4_client_classes_);
1075 data.
add(&host_ipv6_client_classes_);
1079 data.
add(&reserved_ipv6_prefix_address_);
1080 data.
add(&reserved_ipv6_prefix_length_);
1081 data.
add(&reserved_ipv6_prefix_address_type_);
1085 data.
add(&option_universe_);
1086 data.
add(&option_code_);
1087 data.
add(&option_value_);
1088 data.
add(&option_formatted_value_);
1089 data.
add(&option_space_);
1090 data.
add(&option_is_persistent_);
1091 data.
add(&option_client_class_);
1092 data.
add(&option_subnet_id_);
1093 data.
add(&option_user_context_);
1094 data.
add(&option_scope_id_);
1098 "CqlHostExchange::createBindForMutation(): "
1099 "could not create bind array from host "
1100 << host->getHostname() <<
", reason: " << ex.
what());
1108 const std::string& option_space,
1111 prepareExchange(host, subnet_id, reservation, option_space, option_descriptor);
1123 "CqlHostExchange::createBindForDelete(): "
1124 "could not create bind array from host "
1125 << host->getHostname() <<
", reason: " << ex.
what());
1135 std::stringstream key_stream;
1136 if (host_ipv4_address_) {
1139 key_stream << std::setw(10) << std::setfill(
'-') <<
"-";
1143 key_stream << std::setw(10) << std::setfill(
'-') << host_identifier_type_;
1145 key_stream << std::setw(10) << std::setfill(
'-') << host_ipv4_subnet_id_;
1146 key_stream << std::setw(10) << std::setfill(
'-') << host_ipv6_subnet_id_;
1147 key_stream << std::setw(V4ADDRESS_TEXT_MAX_LEN) << std::setfill(
'-')
1148 << host_ipv4_address_;
1149 key_stream << std::setw(V6ADDRESS_TEXT_MAX_LEN) << std::setfill(
'-')
1150 << reserved_ipv6_prefix_address_;
1151 key_stream << std::setw(4) << std::setfill(
'-')
1152 << reserved_ipv6_prefix_length_;
1153 key_stream << std::setw(4) << std::setfill(
'-') << option_code_;
1154 key_stream << std::setw(OPTION_SPACE_MAX_LENGTH) << std::setfill(
'-')
1156 const std::string key = key_stream.str();
1158 const cass_int64_t hash =
static_cast<cass_int64_t
>(
Hash64::hash(key));
1165 const uint64_t
id =
static_cast<uint64_t
>(id_);
1167 HostIdentifier host_identifier =
1168 HostIdentifier(host_identifier_.begin(), host_identifier_.end());
1185 Host* host =
new Host(host_identifier.data(), host_identifier.size(),
1186 host_identifier_type, ipv4_subnet_id, ipv6_subnet_id,
1187 ipv4_reservation, hostname_,
1188 host_ipv4_client_classes_, host_ipv6_client_classes_,
1189 static_cast<uint32_t
>(host_ipv4_next_server_),
1190 host_ipv4_server_hostname_, host_ipv4_boot_file_name_,
1194 if (!user_context_.empty()) {
1199 <<
"' is not a JSON map");
1204 <<
"' is invalid JSON: " << ex.
what());
1211 if (reservation != NULL_IPV6_RESERVATION &&
1217 if (option_wrapper.option_descriptor_) {
1218 if (option_wrapper.option_descriptor_->option_->getUniverse() ==
Option::V4) {
1219 host->
getCfgOption4()->add(*option_wrapper.option_descriptor_,
1220 option_wrapper.option_space_);
1221 }
else if (option_wrapper.option_descriptor_->option_->getUniverse() ==
Option::V6) {
1222 host->
getCfgOption6()->add(*option_wrapper.option_descriptor_,
1223 option_wrapper.option_space_);
1234 switch (reserved_ipv6_prefix_address_type_) {
1241 case NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE:
1242 return (NULL_IPV6_RESERVATION);
1245 "reservation type returned: " << reserved_ipv6_prefix_address_type_
1246 <<
". Only 0 (IA_NA) or 2 (IA_PD) are allowed.");
1250 reserved_ipv6_prefix_length_));
1264 if (option_space_.empty() || option_universe_ == NULL_OPTION_UNIVERSE) {
1276 if (vendor_id > 0) {
1285 if (!option_definition_ptr) {
1286 option_definition_ptr =
1291 if (!option_definition_ptr) {
1293 OptionBuffer option_buffer(option_value_.begin(), option_value_.end());
1295 static_cast<uint16_t
>(option_code_),
1296 option_buffer.begin(), option_buffer.end()));
1304 if (option_formatted_value_.empty()) {
1306 option_value_.end());
1307 option = option_definition_ptr->optionFactory(
1309 static_cast<uint16_t
>(option_code_), option_buffer.begin(),
1310 option_buffer.end());
1314 std::vector<std::string> split_vector;
1315 boost::split(split_vector, option_formatted_value_,
1316 boost::is_any_of(
","));
1317 option = option_definition_ptr->optionFactory(
1319 static_cast<uint16_t
>(option_code_), split_vector);
1324 option_formatted_value_)), option_space_);
1326 if (!option_user_context_.empty()) {
1331 <<
"' is no a JSON map");
1333 result.option_descriptor_->setContext(ctx);
1336 <<
"' is invalid JSON: " << ex.
what());
1385 const uint8_t* identifier_begin,
1386 const size_t identifier_len)
const;
1395 const uint8_t prefix_len)
const;
1407 const uint8_t* identifier_begin,
1408 const size_t identifier_len)
const;
1428 const uint8_t* identifier_begin,
1429 const size_t identifier_len)
const;
1446 virtual std::string
getName()
const;
1464 const IPv6Resrv*
const reservation = NULL,
1465 const std::list<std::string>& option_spaces = std::list<std::string>(),
1485 const std::list<std::string>& option_spaces4,
1487 const std::list<std::string>& option_spaces6,
1533 const IPv6Resrv*
const reservation = NULL,
1534 const std::string& option_space = NULL_OPTION_SPACE,
1564 std::stringstream key_stream;
1565 HostIdentifier host_identifier = std::get<HOST_IDENTIFIER>(key);
1566 key_stream <<
DUID(host_identifier).
toText() <<
"-";
1567 key_stream << std::get<HOST_IDENTIFIER_TYPE>(key) <<
"-";
1568 key_stream << std::get<IPv4_SUBNET_ID>(key) <<
"-";
1569 key_stream << std::get<IPv6_SUBNET_ID>(key) <<
"-";
1570 key_stream << std::get<IPv4_RESERVATION>(key);
1571 const std::string key_string = key_stream.str();
1575 return (
static_cast<std::size_t
>(hash));
1586 return (std::get<HOST_IDENTIFIER>(key1) == std::get<HOST_IDENTIFIER>(key2) &&
1587 std::get<HOST_IDENTIFIER_TYPE>(key1) ==
1588 std::get<HOST_IDENTIFIER_TYPE>(key2) &&
1589 std::get<IPv4_SUBNET_ID>(key1) == std::get<IPv4_SUBNET_ID>(key2) &&
1590 std::get<IPv6_SUBNET_ID>(key1) == std::get<IPv6_SUBNET_ID>(key2) &&
1591 std::get<IPv4_RESERVATION>(key1) == std::get<IPv4_RESERVATION>(key2));
1595 : dbconn_(parameters) {
1605 std::pair<uint32_t, uint32_t> db_version =
getVersion();
1606 if (code_version != db_version) {
1608 << code_version.first <<
"." << code_version.second
1609 <<
" found version: " << db_version.first <<
"."
1610 << db_version.second);
1634 std::list<std::string> option_spaces4 = cfg_option4->getOptionSpaceNames();
1635 std::list<std::string> vendor_spaces4 = cfg_option4->getVendorIdsSpaceNames();
1636 option_spaces4.insert(option_spaces4.end(), vendor_spaces4.begin(),
1637 vendor_spaces4.end());
1641 std::list<std::string> option_spaces6 = cfg_option6->getOptionSpaceNames();
1642 std::list<std::string> vendor_spaces6 = cfg_option6->getVendorIdsSpaceNames();
1643 option_spaces6.insert(option_spaces6.end(), vendor_spaces6.begin(),
1644 vendor_spaces6.end());
1651 if (std::distance(reservations.first, reservations.second) > 0) {
1652 for (
IPv6ResrvIterator it = reservations.first; result && it != reservations.second; ++it) {
1654 option_spaces6, cfg_option6);
1660 option_spaces6, cfg_option6);
1668 if (!address.
isV4()) {
1670 "address supplied is not an IPv4 address");
1674 cass_int32_t host_ipv4_subnet_id =
static_cast<cass_int32_t
>(subnet_id);
1675 cass_int32_t host_ipv4_address =
static_cast<cass_int32_t
>(address.
toUint32());
1679 where_values.
add(&host_ipv4_subnet_id);
1680 where_values.
add(&host_ipv4_address);
1692 const uint8_t* identifier_begin,
1693 const size_t identifier_len)
const {
1695 CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
1696 cass_int32_t host_identifier_type =
static_cast<cass_int32_t
>(identifier_type);
1697 cass_int32_t host_ipv4_subnet_id =
static_cast<cass_int32_t
>(subnet_id);
1701 where_values.
add(&host_ipv4_subnet_id);
1702 where_values.
add(&host_identifier);
1703 where_values.
add(&host_identifier_type);
1714 const uint8_t prefix_len)
const {
1716 std::string reserved_ipv6_prefix_address = prefix.
toText();
1717 cass_int32_t reserved_ipv6_prefix_length = prefix_len;
1722 where_values.
add(&reserved_ipv6_prefix_address);
1723 where_values.
add(&reserved_ipv6_prefix_length);
1733 HostIdentifier host_identifier = host->getIdentifier();
1736 host_identifier.size());
1738 if (collection.empty()) {
1742 if (collection.size() >= 2u) {
1744 "CqlHostDataSource::get6(2): multiple records were "
1746 "database where only one was expected for statement "
1758 const uint8_t* identifier_begin,
1759 const size_t identifier_len)
const {
1761 cass_int32_t host_ipv6_subnet_id =
static_cast<cass_int32_t
>(subnet_id);
1762 CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
1763 cass_int32_t host_identifier_type =
static_cast<cass_int32_t
>(identifier_type);
1767 where_values.
add(&host_ipv6_subnet_id);
1768 where_values.
add(&host_identifier);
1769 where_values.
add(&host_identifier_type);
1781 cass_int32_t host_ipv6_subnet_id =
static_cast<cass_int32_t
>(subnet_id);
1782 std::string reserved_ipv6_prefix_address = address.
toText();
1786 where_values.
add(&host_ipv6_subnet_id);
1787 where_values.
add(&reserved_ipv6_prefix_address);
1798 const uint8_t* identifier_begin,
1799 const size_t identifier_len)
const {
1801 CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
1802 cass_int32_t host_identifier_type =
static_cast<cass_int32_t
>(identifier_type);
1806 where_values.
add(&host_identifier);
1807 where_values.
add(&host_identifier_type);
1819 cass_int32_t host_ipv4_address =
static_cast<cass_int32_t
>(address.
toUint32());
1823 where_values.
add(&host_ipv4_address);
1858 return (version_exchange->retrieveVersion(dbconn_));
1865 const std::list<std::string>& option_spaces,
1876 bool option_found =
false;
1877 for (
const std::string& space : option_spaces) {
1882 if (options && !options->empty()) {
1887 option_found =
true;
1894 if (result && !option_found) {
1906 const std::list<std::string>& option_spaces4,
1908 const std::list<std::string>& option_spaces6,
1919 if (result && cfg_option4 && !cfg_option4->empty()) {
1922 if (result && cfg_option6 && !cfg_option6->empty()) {
1926 (!cfg_option4 || cfg_option4->empty()) &&
1927 (!cfg_option6 || cfg_option6->empty())) {
1939 if (collection.empty()) {
1943 if (collection.size() >= 2u) {
1945 "found in the database where only one was expected for statement "
1949 return (*collection.begin());
1957 std::unique_ptr<CqlHostExchange> host_exchange(
new CqlHostExchange());
1958 AnyArray collection = host_exchange->executeSelect(dbconn_, where_values,
1959 statement_tag,
false);
1963 for (boost::any& host : collection) {
1964 host_collection.push_back(
HostPtr(boost::any_cast<Host*>(host)));
1971 for (
HostPtr& host : host_collection) {
1973 HostKey key = HostKey(host->getIdentifier(), host->getIdentifierType(),
1974 host->getIPv4SubnetID(), host->getIPv6SubnetID(),
1975 host->getIPv4Reservation());
1976 if (map.find(key) == map.end()) {
1984 for (HostPair pair : map) {
1985 result_collection.push_back(pair.second);
1987 return (result_collection);
1995 const std::string& option_space,
2004 std::unique_ptr<CqlHostExchange> host_exchange(
new CqlHostExchange());
2008 host_exchange->createBindForMutation(host, subnet_id, reservation, option_space,
2014 host_exchange->createBindForDelete(host, subnet_id, reservation, option_space,
2035 source_host->getIPv6Reservations();
2036 if (std::distance(reservations_range.first, reservations_range.second) > 0) {
2038 reservations_iterator != reservations_range.second;
2039 ++reservations_iterator) {
2040 if (!target_host->hasReservation(reservations_iterator->second)) {
2041 target_host->addReservation(reservations_iterator->second);
2047 source_host->getCfgOption4()->mergeTo(*target_host->getCfgOption4());
2050 source_host->getCfgOption6()->mergeTo(*target_host->getCfgOption6());
2070 HostPtr host = boost::const_pointer_cast<Host>(impl_->
get4(subnet_id, address));
2077 const uint8_t* identifier_begin,
const size_t identifier_len) {
2078 HostPtr host = boost::const_pointer_cast<Host>(impl_->
get4(subnet_id, identifier_type,
2079 identifier_begin, identifier_len));
2086 const uint8_t* identifier_begin,
const size_t identifier_len) {
2087 HostPtr host = boost::const_pointer_cast<Host>(impl_->
get6(subnet_id, identifier_type,
2088 identifier_begin, identifier_len));
2095 const uint8_t* identifier_begin,
2096 const size_t identifier_len)
const {
2099 return (impl_->
getAll(identifier_type, identifier_begin, identifier_len));
2106 return (impl_->
getAll4(address));
2112 const uint8_t* identifier_begin,
2113 const size_t identifier_len)
const {
2116 return (impl_->
get4(subnet_id, identifier_type, identifier_begin,
2125 return (impl_->
get4(subnet_id, address));
2131 const uint8_t* identifier_begin,
2132 const size_t identifier_len)
const {
2135 return (impl_->
get6(subnet_id, identifier_type, identifier_begin, identifier_len));
2140 const uint8_t prefix_len)
const {
2143 return (impl_->
get6(prefix, prefix_len));
2151 return (impl_->
get6(subnet_id, address));
2161 return std::string(
"cql");
2171 return std::string(
"Host data source that stores host information in the CQL database");
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The IOAddress class represents an IP addresses (version agnostic)
std::string toText() const
Convert the address to a string.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
bool isV4() const
Convenience function to check for an IPv4 address.
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
Structure used to bind C++ input values to dynamic CQL parameters.
void add(const boost::any &value)
Add a value at the end of the vector.
Common CQL connector pool.
void openDatabase()
Open database.
void prepareStatements(StatementMap &statements)
Prepare statements.
Exchange used to retrieve schema version from the keyspace.
static StatementMap tagged_statements_
Cassandra statements.
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Exception thrown on failure to open database.
Exception thrown on failure to execute a database function.
Database duplicate entry error.
Multiple lease records found where one expected.
Database statement not applied.
Implementation of the CqlHostDataSource.
virtual ConstHostCollection getAllHosts() const
Implementation of CqlHostDataSource::getAllHosts()
virtual ConstHostPtr get6(const asiolink::IOAddress &prefix, const uint8_t prefix_len) const
Retrieves a host by its reserved IPv6 address or prefix.
virtual ConstHostPtr getHost(StatementTag statement_tag, AnyArray &where_values) const
Retrieves a single host.
CqlHostDataSourceImpl(const CqlConnection::ParameterMap ¶meters)
Constructor.
virtual VersionPair getVersion() const
Implementation of CqlHostDataSource::getVersion()
virtual void mergeHosts(const ConstHostPtr &source_host, HostPtr &target_host) const
Merge denormalized table entries that belong to the same host into a single host, one by one.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Implementation of CqlHostDataSource::getAll()
virtual bool insertOrDelete(const HostPtr &host, bool insert)
Implementation of CqlHostDataSource::add() and del()
virtual bool insertOrDeleteHostWithReservations(bool insert, const HostPtr &host, const IPv6Resrv *const reservation, const std::list< std::string > &option_spaces4, const ConstCfgOptionPtr cfg_option4, const std::list< std::string > &option_spaces6, const ConstCfgOptionPtr cfg_option6)
Adds/deletes any reservations found in the Host object to/from a separate table entry.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const asiolink::IOAddress &address) const
Implementation of CqlHostDataSource::get4()
virtual bool insertOrDeleteHost(bool insert, const HostPtr &host, const OptionalValue< SubnetID > &subnet_id=OptionalValue< SubnetID >(), const IPv6Resrv *const reservation=NULL, const std::string &option_space=NULL_OPTION_SPACE, const OptionDescriptor &option_descriptor=OptionDescriptor(false))
Inserts or deletes a single host.
virtual ConstHostCollection getHostCollection(StatementTag statement_tag, AnyArray &where_values) const
Retrieves a collection of hosts.
virtual std::string getName() const
Implementation of CqlHostDataSource::getName()
virtual ConstHostCollection getAll4(const asiolink::IOAddress &address) const
Implementation of CqlHostDataSource::getAll4()
virtual bool insertOrDeleteHostWithOptions(bool insert, const HostPtr &host, const IPv6Resrv *const reservation=NULL, const std::list< std::string > &option_spaces=std::list< std::string >(), const ConstCfgOptionPtr cfg_option=ConstCfgOptionPtr())
Adds/deletes any options found in the Host object to/from a separate table entry.
virtual ~CqlHostDataSourceImpl()
Destructor.
CqlHostDataSource(const db::DatabaseConnection::ParameterMap ¶meters)
Constructor.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
virtual bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) override
Attempts to delete a host by (subnet-id6, identifier-type, identifier).
virtual void rollback() override
Rollback Transactions.
virtual ConstHostCollection getAll4(const asiolink::IOAddress &address) const override
Returns a collection of hosts using the specified IPv4 address.
virtual std::string getDescription() const
Returns textual description of the backend.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Returns a Host connected to an IPv6 subnet.
virtual std::string getName() const
Returns the name of the database.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Retrieves a Host connected to an IPv4 subnet.
virtual ~CqlHostDataSource()
Virtual destructor.
virtual bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) override
Attempts to delete a host by (subnet-id4, identifier-type, identifier).
virtual ConstHostCollection getAllHosts() const
Returns a collection of all the hosts.
virtual std::string getType() const override
Return backend type.
virtual void commit() override
Commit Transactions.
virtual void add(const HostPtr &host) override
Adds a new host to the collection.
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr) override
Attempts to delete a host by (subnet-id, address)
virtual db::VersionPair getVersion() const
Retrieves schema version from the DB.
Provides mechanisms for sending and retrieving data from the host_reservations table.
static constexpr StatementTag GET_HOST
void createBindForMutation(const HostPtr &host, const OptionalValue< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor, StatementTag statement_tag, AnyArray &data)
Binds Host to data array to send data to the Cassandra database.
static constexpr StatementTag INSERT_HOST
Statement tags definitions.
static constexpr StatementTag GET_HOST_BY_IPV6_PREFIX
void createBindForDelete(const HostPtr &host, const OptionalValue< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor, StatementTag statement_tag, AnyArray &data)
Binds Host to data array to send data to the Cassandra database.
static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS
static StatementMap tagged_statements_
Cassandra statements.
static constexpr StatementTag GET_HOST_BY_HOST_ID
static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS
static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Binds member variables to data array to receive Host data.
virtual boost::any retrieve() override
Copy received data into Host object.
static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID
static constexpr StatementTag DELETE_HOST
const IPv6Resrv retrieveReservation() const
Creates IPv6 reservation from the data contained in the currently processed row.
virtual ~CqlHostExchange()
Virtual destructor.
cass_int64_t hashIntoId() const
Create unique hash for storage in table id.
void prepareExchange(const HostPtr &host, const OptionalValue< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor)
Sets the exchange members with data of Host.
const OptionWrapper retrieveOption() const
Retrieves option from members.
static constexpr StatementTag GET_HOST_BY_IPV4_ADDRESS
CqlHostExchange()
Constructor.
Holds DUID (DHCPv6 Unique Identifier)
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
static const size_t MAX_DUID_LEN
maximum duid size As defined in RFC 8415, section 11.1
Represents a device with IPv4 and/or IPv6 reservations.
void setHostId(HostID id)
Sets Host ID (primary key in MySQL, PostgreSQL and Cassandra backends)
CfgOptionPtr getCfgOption4()
Returns pointer to the DHCPv4 option data configuration for this host.
IdentifierType
Type of the host identifier.
@ IDENT_FLEX
Flexible host identifier.
void addReservation(const IPv6Resrv &reservation)
Adds new IPv6 reservation.
CfgOptionPtr getCfgOption6()
Returns pointer to the DHCPv6 option data configuration for this host.
bool hasReservation(const IPv6Resrv &reservation) const
Checks if specified IPv6 reservation exists for the host.
IPv6 reservation for a host.
const asiolink::IOAddress & getPrefix() const
Returns prefix for the reservation.
Type getType() const
Returns reservation type.
Type
Type of the reservation.
uint8_t getPrefixLen() const
Returns prefix length.
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const uint16_t code)
Returns vendor option definition for a given vendor-id and code.
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
OptionPtr option_
Option instance.
std::string formatted_value_
Option value in textual (CSV) format.
bool persistent_
Persistence flag.
Universe
defines option universe DHCPv4 or DHCPv6
Simple class representing an optional value.
bool isSpecified() const
Checks if the value is specified or unspecified.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
size_t getLength() const
Return the length of data written in the buffer.
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< const Element > ConstElementPtr
char const *const StatementTag
Statement index representing the statement name.
std::vector< cass_byte_t > CassBlob
Host identifier converted to Cassandra data type.
constexpr uint32_t CQL_SCHEMA_VERSION_MINOR
constexpr uint32_t CQL_SCHEMA_VERSION_MAJOR
Define CQL schema version: 3.0.
std::unordered_map< StatementTag, CqlTaggedStatement, StatementTagHash, StatementTagEqual > StatementMap
A container for all statements.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
std::pair< uint32_t, uint32_t > VersionPair
Pair containing major and minor versions.
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
std::vector< HostPtr > HostCollection
Collection of the Host objects.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
bool operator==(const HostKey &key1, const HostKey &key2)
equals operator for HostKey
boost::shared_ptr< OptionDescriptor > OptionDescriptorPtr
A pointer to option descriptor.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
std::size_t hash_value(const HostKey &key)
hash function for HostMap
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
boost::shared_ptr< Option > OptionPtr
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
Defines the logger used by the top-level component of kea-dhcp-ddns.
#define DHCP4_OPTION_SPACE
#define DHCP6_OPTION_SPACE
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
void setContext(const data::ConstElementPtr &ctx)
Sets user context.
static uint64_t hash(const uint8_t *data, size_t length)
Compute the hash.