1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Implementation of keywords for Honeycomb setup."""
16 from xml.etree import ElementTree as ET
18 from robot.api import logger
20 from resources.libraries.python.topology import NodeType
21 from resources.libraries.python.ssh import SSH
22 from resources.libraries.python.HTTPRequest import HTTPRequest, HTTPCodes, \
24 from resources.libraries.python.HoneycombUtil import HoneycombUtil as HcUtil
25 from resources.libraries.python.HoneycombUtil import HoneycombError
26 from resources.libraries.python.constants import Constants as Const
29 class HoneycombSetup(object):
30 """Implements keywords for Honeycomb setup.
32 The keywords implemented in this class make possible to:
35 - check the Honeycomb start-up state,
36 - check the Honeycomb shutdown state,
37 - add VPP to the topology.
44 def start_honeycomb_on_duts(*nodes):
45 """Start Honeycomb on specified DUT nodes.
47 This keyword starts the Honeycomb service on specified DUTs.
48 The keyword just starts the Honeycomb and does not check its startup
49 state. Use the keyword "Check Honeycomb Startup State" to check if the
50 Honeycomb is up and running.
51 Honeycomb must be installed in "/opt" directory, otherwise the start
53 :param nodes: List of nodes to start Honeycomb on.
55 :raises HoneycombError: If Honeycomb fails to start.
57 logger.console("Starting Honeycomb service ...")
59 cmd = "{0}/start".format(Const.REMOTE_HC_DIR)
62 if node['type'] == NodeType.DUT:
65 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
66 if int(ret_code) != 0:
67 raise HoneycombError('Node {0} failed to start Honeycomb.'.
70 logger.info("Starting the Honeycomb service on node {0} is "
71 "in progress ...".format(node['host']))
74 def stop_honeycomb_on_duts(*nodes):
75 """Stop the Honeycomb service on specified DUT nodes.
77 This keyword stops the Honeycomb service on specified nodes. It just
78 stops the Honeycomb and does not check its shutdown state. Use the
79 keyword "Check Honeycomb Shutdown State" to check if Honeycomb has
81 :param nodes: List of nodes to stop Honeycomb on.
83 :raises HoneycombError: If Honeycomb failed to stop.
85 logger.console("Shutting down Honeycomb service ...")
87 cmd = "{0}/stop".format(Const.REMOTE_HC_DIR)
91 if node['type'] == NodeType.DUT:
94 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
95 if int(ret_code) != 0:
96 errors.append(node['host'])
98 logger.info("Stopping the Honeycomb service on node {0} is "
99 "in progress ...".format(node['host']))
101 raise HoneycombError('Node(s) {0} failed to stop Honeycomb.'.
105 def check_honeycomb_startup_state(*nodes):
106 """Check state of Honeycomb service during startup on specified nodes.
108 Reads html path from template file oper_vpp_version.url.
110 Honeycomb nodes reply with connection refused or the following status
111 codes depending on startup progress: codes 200, 401, 403, 404, 500, 503
113 :param nodes: List of DUT nodes starting Honeycomb.
115 :return: True if all GETs returned code 200(OK).
118 path = HcUtil.read_path_from_url_file("oper_vpp_version")
119 expected_status_codes = (HTTPCodes.UNAUTHORIZED,
122 HTTPCodes.SERVICE_UNAVAILABLE,
123 HTTPCodes.INTERNAL_SERVER_ERROR)
126 if node['type'] == NodeType.DUT:
127 status_code, _ = HTTPRequest.get(node, path, timeout=10,
128 enable_logging=False)
129 if status_code == HTTPCodes.OK:
130 logger.info("Honeycomb on node {0} is up and running".
131 format(node['host']))
132 elif status_code in expected_status_codes:
133 if status_code == HTTPCodes.UNAUTHORIZED:
134 logger.info('Unauthorized. If this triggers keyword '
135 'timeout, verify Honeycomb username and '
137 raise HoneycombError('Honeycomb on node {0} running but '
138 'not yet ready.'.format(node['host']),
139 enable_logging=False)
141 raise HoneycombError('Unexpected return code: {0}.'.
146 def check_honeycomb_shutdown_state(*nodes):
147 """Check state of Honeycomb service during shutdown on specified nodes.
149 Honeycomb nodes reply with connection refused or the following status
150 codes depending on shutdown progress: codes 200, 404.
152 :param nodes: List of DUT nodes stopping Honeycomb.
154 :return: True if all GETs fail to connect.
157 cmd = "ps -ef | grep -v grep | grep karaf"
159 if node['type'] == NodeType.DUT:
161 status_code, _ = HTTPRequest.get(node, '/index.html',
163 enable_logging=False)
164 if status_code == HTTPCodes.OK:
165 raise HoneycombError('Honeycomb on node {0} is still '
166 'running.'.format(node['host']),
167 enable_logging=False)
168 elif status_code == HTTPCodes.NOT_FOUND:
169 raise HoneycombError('Honeycomb on node {0} is shutting'
170 ' down.'.format(node['host']),
171 enable_logging=False)
173 raise HoneycombError('Unexpected return code: {0}.'.
175 except HTTPRequestError:
176 logger.debug('Connection refused, checking the process '
180 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
182 raise HoneycombError('Honeycomb on node {0} is still '
183 'running.'.format(node['host']),
184 enable_logging=False)
186 logger.info("Honeycomb on node {0} has stopped".
187 format(node['host']))
191 def add_vpp_to_honeycomb_network_topology(nodes):
192 """Add vpp node to Honeycomb network topology.
194 :param nodes: All nodes in test topology.
196 :return: Status code and response content from PUT requests.
198 :raises HoneycombError: If a node was not added to Honeycomb topology.
200 Reads HTML path from template file config_topology_node.url.
201 Path to the node to be added, e.g.:
202 ("/restconf/config/network-topology:network-topology"
203 "/topology/topology-netconf/node/")
204 There must be "/" at the end, as generated node name is added at the
207 Reads payload data from template file add_vpp_to_topology.xml.
208 Information about node as XML structure, e.g.:
209 <node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
213 <host xmlns="urn:opendaylight:netconf-node-topology">
216 <port xmlns="urn:opendaylight:netconf-node-topology">
219 <username xmlns="urn:opendaylight:netconf-node-topology">
222 <password xmlns="urn:opendaylight:netconf-node-topology">
225 <tcp-only xmlns="urn:opendaylight:netconf-node-topology">
228 <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">
232 NOTE: The placeholders:
238 MUST be there as they are replaced by correct values.
240 path = HcUtil.read_path_from_url_file("config_topology_node")
242 xml_data = ET.parse("{0}/add_vpp_to_topology.xml".
243 format(Const.RESOURCES_TPL_HC))
244 except ET.ParseError as err:
245 raise HoneycombError(repr(err))
246 data = ET.tostring(xml_data.getroot())
248 headers = {"Content-Type": "application/xml"}
252 for node_name, node in nodes.items():
253 if node['type'] == NodeType.DUT:
255 payload = data.format(
258 vpp_port=node['honeycomb']["netconf_port"],
259 user=node['honeycomb']["user"],
260 passwd=node['honeycomb']["passwd"])
261 status_code, resp = HTTPRequest.put(
263 path="{0}/{1}".format(path, node_name),
266 if status_code != HTTPCodes.OK:
267 raise HoneycombError(
268 "VPP {0} was not added to topology. "
269 "Status code: {1}.".format(node["host"],
272 status_codes.append(status_code)
273 responses.append(resp)
275 except HTTPRequestError as err:
276 raise HoneycombError("VPP {0} was not added to topology.".
277 format(node["host"]), repr(err))
278 return status_codes, responses