try:
self.reporter_agent = Reporter(self.system,
self.__dict__['cephx'],
- f"https://{self.__dict__['mgr_target_ip']}:{self.__dict__['mgr_target_port']}/node-proxy/data")
+ reporter_scheme=self.__dict__.get('reporter_scheme', 'https'),
+ reporter_hostname=self.__dict__['mgr_target_ip'],
+ reporter_port=self.__dict__['mgr_target_port'],
+ reporter_endpoint=self.__dict__.get('reporter_endpoint', '/node-proxy/data'))
except RuntimeError:
self.log.logger.error("Can't initialize the reporter.")
raise
-import ssl
import json
-from urllib.error import URLError
-from urllib.request import urlopen, Request
+from urllib.error import HTTPError, URLError
from .baseclient import BaseClient
-from .util import Logger
+from .util import Logger, http_req
from typing import Dict, Any, Tuple, Optional
+from http.client import HTTPMessage
class RedFishClient(BaseClient):
super().__init__(host, username, password)
self.log: Logger = Logger(__name__)
self.log.logger.info(f"Initializing redfish client {__name__}")
- self.host: str = f"https://{host}:{str(port)}"
+ self.host: str = host
+ self.port: int = port
+ self.url: str = f"https://{self.host}:{self.port}"
self.token: str = ''
self.location: str = ''
def login(self) -> None:
if not self.is_logged_in():
self.log.logger.info("Logging in to "
- f"{self.host} as '{self.username}'")
+ f"{self.url} as '{self.username}'")
idrac_credentials = json.dumps({"UserName": self.username,
"Password": self.password})
headers = {"Content-Type": "application/json"}
headers=headers,
endpoint='/redfish/v1/SessionService/Sessions/')
if _status_code != 201:
- self.log.logger.error(f"Can't log in to {self.host} as '{self.username}': {_status_code}")
+ self.log.logger.error(f"Can't log in to {self.url} as '{self.username}': {_status_code}")
raise RuntimeError
except URLError as e:
- msg = f"Can't log in to {self.host} as '{self.username}': {e}"
+ msg = f"Can't log in to {self.url} as '{self.username}': {e}"
self.log.logger.error(msg)
raise RuntimeError
self.token = _headers['X-Auth-Token']
self.location = _headers['Location']
def is_logged_in(self) -> bool:
- self.log.logger.debug(f"Checking token validity for {self.host}")
+ self.log.logger.debug(f"Checking token validity for {self.url}")
if not self.location or not self.token:
- self.log.logger.debug(f"No token found for {self.host}.")
+ self.log.logger.debug(f"No token found for {self.url}.")
return False
headers = {"X-Auth-Token": self.token}
try:
endpoint=self.location)
except URLError as e:
self.log.logger.error("Can't check token "
- f"validity for {self.host}: {e}")
+ f"validity for {self.url}: {e}")
raise RuntimeError
return _status_code == 200
headers={"X-Auth-Token": self.token},
endpoint=self.location)
except URLError:
- self.log.logger.error(f"Can't log out from {self.host}")
+ self.log.logger.error(f"Can't log out from {self.url}")
return {}
response_str = _data
headers: Dict[str, str] = {},
method: Optional[str] = None,
endpoint: str = '',
- timeout: int = 10) -> Tuple[Dict[str, str], str, int]:
- url = f'{self.host}{endpoint}'
+ timeout: int = 10) -> Tuple[HTTPMessage, str, int]:
_headers = headers.copy() if headers else {}
if self.token:
_headers['X-Auth-Token'] = self.token
if not _headers.get('Content-Type') and method in ['POST', 'PUT', 'PATCH']:
_headers['Content-Type'] = 'application/json'
- # ssl_ctx = ssl.create_default_context()
- # ssl_ctx.check_hostname = True
- # ssl_ctx.verify_mode = ssl.CERT_REQUIRED
- ssl_ctx = ssl._create_unverified_context()
- _data = bytes(data, 'ascii') if data else None
try:
- req = Request(url, _data, headers=_headers, method=method)
- with urlopen(req, context=ssl_ctx, timeout=timeout) as response:
- response_str = response.read()
- response_headers = response.headers
- except URLError as e:
+ (response_headers,
+ response_str,
+ response_status) = http_req(hostname=self.host,
+ port=self.port,
+ endpoint=endpoint,
+ headers=_headers,
+ method=method,
+ data=data,
+ timeout=timeout)
+
+ return response_headers, response_str, response_status
+ except (HTTPError, URLError) as e:
self.log.logger.debug(f"{e}")
raise
-
- return response_headers, response_str, response.status
from threading import Thread
-import requests
import time
-from .util import Logger
+import json
+from .util import Logger, http_req
+from urllib.error import HTTPError, URLError
from typing import Dict, Any
class Reporter:
- def __init__(self, system: Any, cephx: Dict[str, Any], observer_url: str) -> None:
+ def __init__(self,
+ system: Any,
+ cephx: Dict[str, Any],
+ reporter_scheme: str = 'https',
+ reporter_hostname: str = '',
+ reporter_port: int = 443,
+ reporter_endpoint: str = '/node-proxy/data') -> None:
self.system = system
- self.observer_url = observer_url
+ self.data: Dict[str, Any] = {}
self.finish = False
self.cephx = cephx
+ self.data['cephx'] = self.cephx
+ self.reporter_scheme: str = reporter_scheme
+ self.reporter_hostname: str = reporter_hostname
+ self.reporter_port: int = reporter_port
+ self.reporter_endpoint: str = reporter_endpoint
self.log = Logger(__name__)
- self.log.logger.info(f'Observer url set to {self.observer_url}')
+ self.reporter_url: str = (f"{reporter_scheme}:{reporter_hostname}:"
+ f"{reporter_port}{reporter_endpoint}")
+ self.log.logger.info(f'Reporter url set to {self.reporter_url}')
def stop(self) -> None:
self.finish = True
self.log.logger.info('data ready to be sent to the mgr.')
if not self.system.get_system() == self.system.previous_data:
self.log.logger.info('data has changed since last iteration.')
- self.data = {}
- self.data['cephx'] = self.cephx
self.data['patch'] = self.system.get_system()
try:
# TODO: add a timeout parameter to the reporter in the config file
- self.log.logger.info(f"sending data to {self.observer_url}")
- r = requests.post(f"{self.observer_url}", json=self.data, timeout=5, verify=False)
- except (requests.exceptions.RequestException,
- requests.exceptions.ConnectionError) as e:
+ self.log.logger.info(f"sending data to {self.reporter_url}")
+ http_req(hostname=self.reporter_hostname,
+ port=self.reporter_port,
+ method='POST',
+ headers={'Content-Type': 'application/json'},
+ endpoint=self.reporter_endpoint,
+ scheme=self.reporter_scheme,
+ data=json.dumps(self.data))
+ except (HTTPError, URLError) as e:
self.log.logger.error(f"The reporter couldn't send data to the mgr: {e}")
# Need to add a new parameter 'max_retries' to the reporter if it can't
# send the data for more than x times, maybe the daemon should stop altogether
import os
import time
import re
-from typing import Dict, List, Callable, Any
+import ssl
+from urllib.error import HTTPError, URLError
+from urllib.request import urlopen, Request
+from typing import Dict, List, Callable, Any, Optional, MutableMapping, Tuple
class Logger:
return f(*args, **kwargs)
return _retry
return decorator
+
+
+def http_req(hostname: str = '',
+ port: int = 443,
+ method: Optional[str] = None,
+ headers: MutableMapping[str, str] = {},
+ data: Optional[str] = None,
+ endpoint: str = '/',
+ scheme: str = 'https',
+ ssl_verify: bool = False,
+ timeout: Optional[int] = None,
+ ssl_ctx: Optional[Any] = None) -> Tuple[Any, Any, Any]:
+
+ if not ssl_ctx:
+ ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+ if not ssl_verify:
+ ssl_ctx.check_hostname = False
+ ssl_ctx.verify_mode = ssl.CERT_NONE
+ else:
+ ssl_ctx.verify_mode = ssl.CERT_REQUIRED
+
+ url: str = f'{scheme}://{hostname}:{str(port)}{endpoint}'
+ _data = bytes(data, 'ascii') if data else None
+
+ try:
+ req = Request(url, _data, headers, method=method)
+ with urlopen(req, context=ssl_ctx, timeout=timeout) as response:
+ response_str = response.read()
+ response_headers = response.headers
+ response_code = response.code
+ return response_headers, response_str.decode(), response_code
+ except (HTTPError, URLError) as e:
+ print(f'{e}')
+ # handle error here if needed
+ raise