Add output.xml with only INFO logging leve
[csit.git] / resources / libraries / python / HTTPRequest.py
index 1f5df52..0f650a8 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 Cisco and/or its affiliates.
+# Copyright (c) 2018 Cisco and/or its affiliates.
 # 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:
 # 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:
@@ -18,10 +18,12 @@ The HTTP requests are implemented in the class HTTPRequest which uses
 requests.request.
 """
 
 requests.request.
 """
 
+from ipaddress import IPv6Address, AddressValueError
 from enum import IntEnum, unique
 
 from robot.api.deco import keyword
 from robot.api import logger
 from enum import IntEnum, unique
 
 from robot.api.deco import keyword
 from robot.api import logger
+from robot.libraries.BuiltIn import BuiltIn
 
 from requests import request, RequestException, Timeout, TooManyRedirects, \
     HTTPError, ConnectionError
 
 from requests import request, RequestException, Timeout, TooManyRedirects, \
     HTTPError, ConnectionError
@@ -31,11 +33,12 @@ from requests.auth import HTTPBasicAuth
 @unique
 class HTTPCodes(IntEnum):
     """HTTP status codes"""
 @unique
 class HTTPCodes(IntEnum):
     """HTTP status codes"""
-    OK = 200
+    OK = 200  # HTTP standard code name.  # pylint: disable=invalid-name
     ACCEPTED = 201
     UNAUTHORIZED = 401
     FORBIDDEN = 403
     NOT_FOUND = 404
     ACCEPTED = 201
     UNAUTHORIZED = 401
     FORBIDDEN = 403
     NOT_FOUND = 404
+    CONFLICT = 409
     INTERNAL_SERVER_ERROR = 500
     SERVICE_UNAVAILABLE = 503
 
     INTERNAL_SERVER_ERROR = 500
     SERVICE_UNAVAILABLE = 503
 
@@ -45,10 +48,12 @@ class HTTPRequestError(Exception):
 
     When raising this exception, put this information to the message in this
     order:
 
     When raising this exception, put this information to the message in this
     order:
-    - short description of the encountered problem,
-    - relevant messages if there are any collected, e.g., from caught
-      exception,
-    - relevant data if there are any collected.
+
+     - short description of the encountered problem,
+     - relevant messages if there are any collected, e.g., from caught
+       exception,
+     - relevant data if there are any collected.
+
     The logging is performed on two levels: 1. error - short description of the
     problem; 2. debug - detailed information.
     """
     The logging is performed on two levels: 1. error - short description of the
     problem; 2. debug - detailed information.
     """
@@ -62,7 +67,7 @@ class HTTPRequestError(Exception):
 
         :param msg: Message to be displayed and logged.
         :param enable_logging: When True, logging is enabled, otherwise
 
         :param msg: Message to be displayed and logged.
         :param enable_logging: When True, logging is enabled, otherwise
-        logging is disabled.
+            logging is disabled.
         :type msg: str
         :type enable_logging: bool
         """
         :type msg: str
         :type enable_logging: bool
         """
@@ -70,7 +75,7 @@ class HTTPRequestError(Exception):
         self._msg = "{0}: {1}".format(self.__class__.__name__, msg)
         self._details = details
         if enable_logging:
         self._msg = "{0}: {1}".format(self.__class__.__name__, msg)
         self._details = details
         if enable_logging:
-            logger.error(self._msg)
+            logger.info(self._msg)
             logger.debug(self._details)
 
     def __repr__(self):
             logger.debug(self._details)
 
     def __repr__(self):
@@ -110,9 +115,17 @@ class HTTPRequest(object):
         :type ip_addr: str
         :type port: str or int
         :type path: str
         :type ip_addr: str
         :type port: str or int
         :type path: str
-        :return: Full url.
+        :returns: Full url.
         :rtype: str
         """
         :rtype: str
         """
+
+        try:
+            IPv6Address(unicode(ip_addr))
+            # IPv6 address must be in brackets
+            ip_addr = "[{0}]".format(ip_addr)
+        except (AttributeError, AddressValueError):
+            pass
+
         return "http://{ip}:{port}{path}".format(ip=ip_addr, port=port,
                                                  path=path)
 
         return "http://{ip}:{port}{path}".format(ip=ip_addr, port=port,
                                                  path=path)
 
@@ -157,7 +170,7 @@ class HTTPRequest(object):
         :type path: str
         :type enable_logging: bool
         :type kwargs: dict
         :type path: str
         :type enable_logging: bool
         :type kwargs: dict
-        :return: Status code and content of response.
+        :returns: Status code and content of response.
         :rtype: tuple
         :raises HTTPRequestError: If
         1. it is not possible to connect,
         :rtype: tuple
         :raises HTTPRequestError: If
         1. it is not possible to connect,
@@ -167,13 +180,31 @@ class HTTPRequest(object):
         5. there is any other unexpected HTTP request exception.
         """
         timeout = kwargs["timeout"]
         5. there is any other unexpected HTTP request exception.
         """
         timeout = kwargs["timeout"]
+
+        use_odl = BuiltIn().get_variable_value("${use_odl_client}")
+
+        if use_odl:
+            port = 8181
+            # Using default ODL Restconf port
+            # TODO: add node["honeycomb"]["odl_port"] to topology, use it here
+            odl_url_part = "/network-topology:network-topology/topology/" \
+                           "topology-netconf/node/vpp/yang-ext:mount"
+        else:
+            port = node["honeycomb"]["port"]
+            odl_url_part = ""
+
+        try:
+            path = path.format(odl_url_part=odl_url_part)
+        except KeyError:
+            pass
+
         url = HTTPRequest.create_full_url(node['host'],
         url = HTTPRequest.create_full_url(node['host'],
-                                          node['honeycomb']['port'],
+                                          port,
                                           path)
         try:
             auth = HTTPBasicAuth(node['honeycomb']['user'],
                                  node['honeycomb']['passwd'])
                                           path)
         try:
             auth = HTTPBasicAuth(node['honeycomb']['user'],
                                  node['honeycomb']['passwd'])
-            rsp = request(method, url, auth=auth, **kwargs)
+            rsp = request(method, url, auth=auth, verify=False, **kwargs)
 
             logger.debug("Status code: {0}".format(rsp.status_code))
             logger.debug("Response: {0}".format(rsp.content))
 
             logger.debug("Status code: {0}".format(rsp.status_code))
             logger.debug("Response: {0}".format(rsp.content))
@@ -202,23 +233,23 @@ class HTTPRequest(object):
 
     @staticmethod
     @keyword(name="HTTP Get")
 
     @staticmethod
     @keyword(name="HTTP Get")
-    def get(node, path, headers=None, timeout=10, enable_logging=True):
+    def get(node, path, headers=None, timeout=15, enable_logging=True):
         """Sends a GET request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param timeout: How long to wait for the server to send data before
         """Sends a GET request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param timeout: How long to wait for the server to send data before
-        giving up, as a float, or a (connect timeout, read timeout) tuple.
+            giving up, as a float, or a (connect timeout, read timeout) tuple.
         :param enable_logging: Used to suppress errors when checking Honeycomb
         :param enable_logging: Used to suppress errors when checking Honeycomb
-        state during suite setup and teardown. When True, logging is enabled,
-        otherwise logging is disabled.
+            state during suite setup and teardown. When True,
+            logging is enabled, otherwise logging is disabled.
         :type node: dict
         :type path: str
         :type headers: dict
         :type timeout: float or tuple
         :type enable_logging: bool
         :type node: dict
         :type path: str
         :type headers: dict
         :type timeout: float or tuple
         :type enable_logging: bool
-        :return: Status code and content of response.
+        :returns: Status code and content of response.
         :rtype: tuple
         """
 
         :rtype: tuple
         """
 
@@ -228,24 +259,24 @@ class HTTPRequest(object):
 
     @staticmethod
     @keyword(name="HTTP Put")
 
     @staticmethod
     @keyword(name="HTTP Put")
-    def put(node, path, headers=None, payload=None, json=None, timeout=10):
+    def put(node, path, headers=None, payload=None, json=None, timeout=15):
         """Sends a PUT request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param payload: Dictionary, bytes, or file-like object to send in
         """Sends a PUT request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param payload: Dictionary, bytes, or file-like object to send in
-        the body of the Request.
+            the body of the Request.
         :param json: JSON formatted string to send in the body of the Request.
         :param timeout: How long to wait for the server to send data before
         :param json: JSON formatted string to send in the body of the Request.
         :param timeout: How long to wait for the server to send data before
-        giving up, as a float, or a (connect timeout, read timeout) tuple.
+            giving up, as a float, or a (connect timeout, read timeout) tuple.
         :type node: dict
         :type path: str
         :type headers: dict
         :type payload: dict, bytes, or file-like object
         :type json: str
         :type timeout: float or tuple
         :type node: dict
         :type path: str
         :type headers: dict
         :type payload: dict, bytes, or file-like object
         :type json: str
         :type timeout: float or tuple
-        :return: Status code and content of response.
+        :returns: Status code and content of response.
         :rtype: tuple
         """
         return HTTPRequest._http_request('PUT', node, path, headers=headers,
         :rtype: tuple
         """
         return HTTPRequest._http_request('PUT', node, path, headers=headers,
@@ -254,43 +285,49 @@ class HTTPRequest(object):
 
     @staticmethod
     @keyword(name="HTTP Post")
 
     @staticmethod
     @keyword(name="HTTP Post")
-    def post(node, path, headers=None, payload=None, json=None, timeout=10):
+    def post(node, path, headers=None, payload=None, json=None, timeout=15,
+             enable_logging=True):
         """Sends a POST request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param payload: Dictionary, bytes, or file-like object to send in
         """Sends a POST request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param headers: Dictionary of HTTP Headers to send with the Request.
         :param payload: Dictionary, bytes, or file-like object to send in
-        the body of the Request.
+            the body of the Request.
         :param json: JSON formatted string to send in the body of the Request.
         :param timeout: How long to wait for the server to send data before
         :param json: JSON formatted string to send in the body of the Request.
         :param timeout: How long to wait for the server to send data before
-        giving up, as a float, or a (connect timeout, read timeout) tuple.
+            giving up, as a float, or a (connect timeout, read timeout) tuple.
+        :param enable_logging: Used to suppress errors when checking ODL
+            state during suite setup and teardown. When True,
+            logging is enabled, otherwise logging is disabled.
         :type node: dict
         :type path: str
         :type headers: dict
         :type payload: dict, bytes, or file-like object
         :type json: str
         :type timeout: float or tuple
         :type node: dict
         :type path: str
         :type headers: dict
         :type payload: dict, bytes, or file-like object
         :type json: str
         :type timeout: float or tuple
-        :return: Status code and content of response.
+        :type enable_logging: bool
+        :returns: Status code and content of response.
         :rtype: tuple
         """
         :rtype: tuple
         """
-        return HTTPRequest._http_request('POST', node, path, headers=headers,
-                                         data=payload, json=json,
-                                         timeout=timeout)
+        return HTTPRequest._http_request('POST', node, path,
+                                         enable_logging=enable_logging,
+                                         headers=headers, data=payload,
+                                         json=json, timeout=timeout)
 
     @staticmethod
     @keyword(name="HTTP Delete")
 
     @staticmethod
     @keyword(name="HTTP Delete")
-    def delete(node, path, timeout=10):
+    def delete(node, path, timeout=15):
         """Sends a DELETE request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param timeout: How long to wait for the server to send data before
         """Sends a DELETE request and returns the response and status code.
 
         :param node: Honeycomb node.
         :param path: URL path, e.g. /index.html.
         :param timeout: How long to wait for the server to send data before
-        giving up, as a float, or a (connect timeout, read timeout) tuple.
+            giving up, as a float, or a (connect timeout, read timeout) tuple.
         :type node: dict
         :type path: str
         :type timeout: float or tuple
         :type node: dict
         :type path: str
         :type timeout: float or tuple
-        :return: Status code and content of response.
+        :returns: Status code and content of response.
         :rtype: tuple
         """
         return HTTPRequest._http_request('DELETE', node, path, timeout=timeout)
         :rtype: tuple
         """
         return HTTPRequest._http_request('DELETE', node, path, timeout=timeout)