... TODO: Unify capitalization of Leaders and Followers.
Library RequestsLibrary # for Create_Session and To_Json
Library Collections
+Library ClusterEntities.py
Resource ${CURDIR}/CompareStream.robot
Resource ${CURDIR}/KarafKeywords.robot
Resource ${CURDIR}/SSHKeywords.robot
*** Variables ***
${ENTITY_OWNER_URI} restconf/operational/entity-owners:entity-owners
+${RESTCONF_URI} rests
${GC_LOG_PATH} ${KARAF_HOME}/data/log
${JAVA_HOME} ${EMPTY} # releng/builder scripts should provide correct value
${JOLOKIA_CONF_SHARD_MANAGER_URI} jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
${JOLOKIA_OPER_LOCAL_SHARDS_URI} jolokia/read/org.opendaylight.controller:type=DistributedOperationalDatastore,Category=ShardManager,name=shard-manager-operational/LocalShards
${JOLOKIA_READ_URI} jolokia/read/org.opendaylight.controller
# Bug 9044 workaround: delete etc/host.key before restart.
-@{ODL_DEFAULT_DATA_PATHS} tmp/ data/ cache/ snapshots/ journal/ etc/opendaylight/current/ etc/host.key
+@{ODL_DEFAULT_DATA_PATHS} tmp/ data/ cache/ snapshots/ journal/ segmented-journal/ etc/opendaylight/current/ etc/host.key
${RESTCONF_MODULES_DIR} ${CURDIR}/../variables/restconf/modules
${SINGLETON_NETCONF_DEVICE_ID_PREFIX_OLD} /odl-general-entity:entity[odl-general-entity:name='KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node, path=[org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology[key=TopologyKey [_topologyId=Uri [_value=topology-netconf]]], org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node[key=NodeKey [_nodeId=Uri [_value=
${SINGLETON_NETCONF_DEVICE_ID_SUFFIX_OLD} ]]]]}']
-${SINGLETON_NETCONF_DEVICE_ID_PREFIX} /odl-general-entity:entity[odl-general-entity:name='KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node, path=[org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology[key=TopologyKey{_topologyId=Uri{_value=topology-netconf}}], org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node[key=NodeKey{_nodeId=Uri{_value=
-${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} }}]]}']
+${SINGLETON_NETCONF_DEVICE_ID_PREFIX} KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node, path=[org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology, org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology[key=TopologyKey{_topologyId=Uri{_value=topology-netconf}}], org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node[key=NodeKey{_nodeId=Uri{_value=
+${SINGLETON_NETCONF_DEVICE_ID_SUFFIX} }}]]}
${SINGLETON_BGPCEP_DEVICE_ID_PREFIX} /odl-general-entity:entity[odl-general-entity:name='
${SINGLETON_BGPCEP_DEVICE_ID_SUFFIX} -service-group']
${SINGLETON_SXP_DEVICE_ID_PREFIX} /odl-general-entity:entity[odl-general-entity:name='
... http_timeout=${http_timeout}
[Return] ${raft_state}
+Get_Raft_State_Of_Shard_Of_All_Member_Nodes
+ [Arguments] ${shard_name}=default ${shard_type}=config ${member_index_list}=${EMPTY}
+ [Documentation] Get raft state of shard of all member nodes
+ ${index_list} = List_Indices_Or_All given_list=${member_index_list}
+ Collections.Sort_List ${index_list}
+ FOR ${index} IN @{index_list}
+ ClusterManagement.Get Raft State Of Shard At Member shard_name=${shard_name} shard_type=${shard_type} member_index=${index}
+ END
+
Get_Raft_Property_From_Shard_Member
[Arguments] ${property} ${shard_name} ${shard_type} ${member_index} ${verify_restconf}=False ${http_timeout}=${EMPTY}
[Documentation] Send request to Jolokia on indexed member, return extracted Raft property.
Collections.Remove_Values_From_List ${successor_list} ${owner}
[Return] ${owner} ${successor_list}
-Get_Owner_And_Candidates_For_Device_Old
+Get_Owner_And_Candidates_For_Device_Rpc
[Arguments] ${device_name} ${device_type} ${member_index} ${http_timeout}=${EMPTY}
[Documentation] Returns the owner and a list of candidates for the SB device ${device_name} of type ${device_type}. Request is sent to member ${member_index}.
... Candidates are all members that register to own a device, so the list of candiates includes the owner.
... Note that "candidate list" definition currently differs between Beryllium and Boron.
... It is recommended to use Get_Owner_And_Successors_For_Device instead of this keyword, see documentation there.
BuiltIn.Comment TODO: Can this implementation be changed to call Get_Owner_And_Candidates_For_Type_And_Id?
- ${session} = Resolve_Http_Session_For_Member member_index=${member_index}
- ${data} = TemplatedRequests.Get_As_Json_From_Uri uri=${ENTITY_OWNER_URI} session=${session} http_timeout=${http_timeout}
- ${candidate_list} = BuiltIn.Create_List
+ ${index} = BuiltIn.Convert_To_Integer ${member_index}
+ ${ip} = Resolve_IP_Address_For_Member member_index=${index}
${entity_type} = BuiltIn.Set_Variable_If '${device_type}' == 'netconf' netconf-node/${device_name} ${device_type}
- ${clear_data} = BuiltIn.Run_Keyword_If '${device_type}' == 'openflow' or '${device_type}' == 'netconf' Extract_OpenFlow_Device_Data ${data}
- ... ELSE IF '${device_type}' == 'ovsdb' Extract_Ovsdb_Device_Data ${data}
- ... ELSE IF '${device_type}' == 'org.opendaylight.mdsal.ServiceEntityType' Extract_Service_Entity_Type ${data}
- ... ELSE Fail Not recognized device type: ${device_type}
- ${json} = RequestsLibrary.To_Json ${clear_data}
- ${entity_type_list} = Collections.Get_From_Dictionary &{json}[entity-owners] entity-type
- ${entity_type_index} = Utils.Get_Index_From_List_Of_Dictionaries ${entity_type_list} type ${entity_type}
- BuiltIn.Should_Not_Be_Equal_As_Integers ${entity_type_index} -1 No Entity Owner found for ${device_type}
- ${entity_list} = Collections.Get_From_Dictionary @{entity_type_list}[${entity_type_index}] entity
- ${entity_index} = Utils.Get_Index_From_List_Of_Dictionaries ${entity_list} id ${device_name}
- BuiltIn.Should_Not_Be_Equal_As_Integers ${entity_index} -1 Device ${device_name} not found in Entity Owner ${device_type}
- ${entity_owner} = Collections.Get_From_Dictionary @{entity_list}[${entity_index}] owner
+ ${url} = BuiltIn.Catenate SEPARATOR= http:// ${ip} :8181/ ${RESTCONF_URI}
+ ${entity_result} = ClusterEntities.get entity ${url} ${entity_type} ${device_name}
+ ${entity_candidates} = Collections.Get_From_Dictionary ${entity_result} candidates
+ ${entity_owner} = Collections.Get_From_Dictionary ${entity_result} owner
BuiltIn.Should_Not_Be_Empty ${entity_owner} No owner found for ${device_name}
${owner} = String.Replace_String ${entity_owner} member- ${EMPTY}
${owner} = BuiltIn.Convert_To_Integer ${owner}
- ${entity_candidates_list} = Collections.Get_From_Dictionary @{entity_list}[${entity_index}] candidate
- FOR ${entity_candidate} IN @{entity_candidates_list}
- ${candidate} = String.Replace_String &{entity_candidate}[name] member- ${EMPTY}
+ ${candidate_list} = BuiltIn.Create_List
+ FOR ${entity_candidate} IN @{entity_candidates}
+ ${candidate} = String.Replace_String ${entity_candidate} member- ${EMPTY}
${candidate} = BuiltIn.Convert_To_Integer ${candidate}
Collections.Append_To_List ${candidate_list} ${candidate}
END
... http_timeout=${http_timeout}
BuiltIn.Return_From_Keyword_If "${status}"=="PASS" ${results}
# If singleton failed, try parsing in old way
- ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error Get_Owner_And_Candidates_For_Device_Old device_name=${device_name} device_type=${device_type} member_index=${member_index}
+ ${status} ${results} = BuiltIn.Run_Keyword_And_Ignore_Error Get_Owner_And_Candidates_For_Device_Rpc device_name=${device_name} device_type=${device_type} member_index=${member_index}
... http_timeout=${http_timeout}
# previous 3 lines (BuilIn.Return.., # If singleton..., ${status}....) could be deleted when old way will not be supported anymore
BuiltIn.Run_Keyword_If '${status}'=='FAIL' BuiltIn.Fail Could not parse owner and candidates for device ${device_name}
... Note that differs from "given list" semantics used in other keywords,
... namely you cannot use \${EMPTY} to stand for "full list" in this keyword.
BuiltIn.Comment TODO: Find a way to unify and deduplicate code blocks in Get_Owner_And_Candidates_* keywords.
- ${session} = Resolve_Http_Session_For_Member member_index=${member_index}
- ${data} = TemplatedRequests.Get_As_Json_From_Uri uri=${ENTITY_OWNER_URI} session=${session} http_timeout=${http_timeout}
- ${candidate_list} = BuiltIn.Create_List
- ${json} = RequestsLibrary.To_Json ${data}
- ${entity_type_list} = Collections.Get_From_Dictionary &{json}[entity-owners] entity-type
- ${entity_type_index} = Utils.Get_Index_From_List_Of_Dictionaries ${entity_type_list} type ${type}
- BuiltIn.Should_Not_Be_Equal_As_Integers ${entity_type_index} -1 No Entity Owner found for ${type}
- ${entity_list} = Collections.Get_From_Dictionary @{entity_type_list}[${entity_type_index}] entity
- ${entity_index} = Utils.Get_Index_From_List_Of_Dictionaries ${entity_list} id ${id}
- BuiltIn.Should Not_Be_Equal_As_Integers ${entity_index} -1 Id ${id} not found in Entity Owner ${type}
- ${entity_owner} = Collections.Get_From_Dictionary @{entity_list}[${entity_index}] owner
- BuiltIn.Should_Not_Be_Empty ${entity_owner} No owner found for type=${type} id=${id}
- ${owner} = String.Replace_String ${entity_owner} member- ${EMPTY}
- ${owner} = BuiltIn.Convert_To_Integer ${owner}
- ${entity_candidates_list} = Collections.Get_From_Dictionary @{entity_list}[${entity_index}] candidate
- FOR ${entity_candidate} IN @{entity_candidates_list}
- ${candidate} = String.Replace_String &{entity_candidate}[name] member- ${EMPTY}
- ${candidate} = BuiltIn.Convert_To_Integer ${candidate}
- Collections.Append_To_List ${candidate_list} ${candidate}
- END
- Collections.Sort_List ${candidate_list}
- BuiltIn.Comment TODO: Separate check lines into Verify_Owner_And_Candidates_For_Type_And_Id
- BuiltIn.Run_Keyword_If """${require_candidate_list}""" BuiltIn.Should_Be_Equal ${require_candidate_list} ${candidate_list} Candidate list does not match: ${candidate_list} is not ${require_candidate_list}
- [Return] ${owner} ${candidate_list}
+ ${owner} ${candidates} = Get_Owner_And_Candidates_For_Device_Rpc ${id} ${type} ${member_index} http_timeout=${http_timeout}
+ [Return] ${owner} ${candidates}
Extract_Service_Entity_Type
[Arguments] ${data}
[Return] ${updated_index_list}
Stop_Members_From_List_Or_All
- [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True ${timeout}=240s
+ [Arguments] ${member_index_list}=${EMPTY} ${original_index_list}=${EMPTY} ${confirm}=True ${timeout}=360s
[Documentation] If the list is empty, stops all ODL instances. Otherwise stop members based on \${stop_index_list}
... If \${confirm} is True, verify stopped instances are not there anymore.
... The KW will return a list of available members: \${updated index_list}=\${original_index_list}-\${member_index_list}
Start_Members_From_List_Or_All ${index_list} ${wait_for_sync} ${timeout} check_system_status=${check_system_status} verify_restconf=${verify_restconf} service_list=${service_list}
Start_Members_From_List_Or_All
- [Arguments] ${member_index_list}=${EMPTY} ${wait_for_sync}=True ${timeout}=300s ${karaf_home}=${EMPTY} ${export_java_home}=${EMPTY} ${gc_log_dir}=${EMPTY}
+ [Arguments] ${member_index_list}=${EMPTY} ${wait_for_sync}=True ${timeout}=360s ${karaf_home}=${EMPTY} ${export_java_home}=${EMPTY} ${gc_log_dir}=${EMPTY}
... ${check_system_status}=False ${verify_restconf}=True ${service_list}=${EMPTY_LIST}
[Documentation] If the list is empty, start all cluster members. Otherwise, start members based on present indices.
... If ${wait_for_sync}, wait for cluster sync on listed members.
... BEWARE: If only a subset of members is cleaned, this causes RetiredGenerationException in Carbon after the affected node re-start.
... See https://bugs.opendaylight.org/show_bug.cgi?id=8138
${index_list} = List_Indices_Or_All given_list=${member_index_list}
- ${command} = Set Variable rm -rf "${karaf_home}/journal" "${karaf_home}/snapshots" "${karaf_home}/data"
+ ${command} = Set Variable rm -rf "${karaf_home}/"*journal "${karaf_home}/snapshots" "${karaf_home}/data"
FOR ${index} IN @{index_list} # usually: 1, 2, 3.
Run_Bash_Command_On_Member command=${command} member_index=${index}
END