def test_login_with_specific_login_domain_for_multiple_ov( self, get_authentication_mode, get_oneview_multiple_ips, oneview_client_mockup): get_authentication_mode.return_value = 'session' tokens_ov = collections.OrderedDict({ '10.0.0.1': 'abc', '10.0.0.2': 'def', '10.0.0.3': 'ghi' }) list_ips = list(tokens_ov.keys()) client_session.init_map_clients() get_oneview_multiple_ips.return_value = list_ips client_session.login('SOME_DOMAIN\\user', 'password123') oneview_client_mockup.assert_any_call({ 'ip': '10.0.0.1', 'credentials': { 'userName': '******', 'password': '******', 'authLoginDomain': 'SOME_DOMAIN' }, 'api_version': 600 })
def _build_common_sessions(self, uuid_mock): uuid_mock.uuid4.side_effect = self.session_ids client_session.init_map_clients() client_session._set_new_client_by_token('abc', '10.0.0.1') client_session._set_new_client_by_token('def', '10.0.0.2') client_session._set_new_client_by_token('ghi', '10.0.0.3')
def setUp(self): # Initializing caches multiple_oneview.init_map_resources() client_session.init_map_clients() category_resource.init_map_category_resources() self.config_obj = configparser.ConfigParser() self.config_obj.add_section('oneview_config') self.config_obj.add_section('redfish')
def test_map_token_redfish_for_multiple_ov(self, get_authentication_mode, get_oneview_multiple_ips, oneview_client_mockup, uuid_mock): get_authentication_mode.return_value = 'session' mocked_rf_token = "abc" session_id = '123456' list_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3'] conn_1 = mock.MagicMock() connection_list = [conn_1, mock.MagicMock(), mock.MagicMock()] connections_ov = collections.OrderedDict({ 'client_ov_by_ip': { list_ips[0]: connection_list[0], list_ips[1]: connection_list[1], list_ips[2]: connection_list[2] }, 'session_id': session_id }) uuid_mock.uuid4.return_value = session_id iter_conns_ov = iter(connection_list) client_session.init_map_clients() get_oneview_multiple_ips.return_value = list_ips def function_returning_token(ov_config): return next(iter_conns_ov) oneview_client_mockup.side_effect = function_returning_token conn_1.connection.get_session_id.return_value = mocked_rf_token # Check if redfish token return is one of the OneView's token rf_token, _ = client_session.login('user', 'password') oneview_client_mockup.assert_any_call({ 'ip': '10.0.0.1', 'credentials': { 'userName': '******', 'password': '******' }, 'api_version': 600 }) self.assertEqual(rf_token, mocked_rf_token) # Check if cached connection map has the Redfish token return on login map_clients = client_session._get_map_clients() self.assertTrue(rf_token in map_clients) # Check if cached connection map has the correct # OneViewIp/OneViewConnection tuples for ov_ip, ov_conn in map_clients[rf_token].items(): self.assertEqual(connections_ov[ov_ip], ov_conn)
def test_post_session(self, get_authentication_mode, oneview_client_mockup, uuid_mock): """Tests post Session""" # Loading Session mockup result with open('oneview_redfish_toolkit/mockups/redfish/Session.json') as f: expected_session_mockup = json.load(f) client_session.init_map_clients() multiple_oneview.init_map_appliances() get_authentication_mode.return_value = 'session' # Create mock response uuid_mock.uuid4.return_value = self.session_id oneview_client = oneview_client_mockup() oneview_client.connection.get_session_id.return_value = self.token_id # POST Session response = self.client.post("/redfish/v1/SessionService/Sessions", data=json.dumps( dict(UserName="******", Password="******")), content_type='application/json') # Gets json from response result = json.loads(response.data.decode("utf-8")) # Tests response self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual("application/json", response.mimetype) self.assertEqualMockup(expected_session_mockup, result) self.assertIn("/redfish/v1/SessionService/Sessions/" + self.session_id, response.headers["Location"]) self.assertEqual(self.token_id, response.headers["X-Auth-Token"]) oneview_client_mockup.assert_called_with({ 'ip': config.get_oneview_multiple_ips()[0], 'credentials': { 'userName': '******', 'password': '******' }, 'api_version': config.get_api_version() }) # gets the session by id response_of_get = self.client.get(response.headers["Location"], content_type='application/json') result_of_get = json.loads(response_of_get.data.decode("utf-8")) self.assertEqual(status.HTTP_200_OK, response_of_get.status_code) self.assertEqual(self.session_id, result_of_get["Id"])
def test_get_session_when_is_not_cached(self, _, uuid_mock): """Tests get a specific Session when session id is not present""" uuid_mock.uuid4.return_value = '709cf49b-f367-417e-af70-ede782e0fa3c' client_session.init_map_clients() client_session._set_new_client_by_token('abc', '10.0.0.1') response = self.client.get( "/redfish/v1/SessionService/Sessions/" "e2807c0b-87d6-4304-a773-6ec33521fb1c", content_type='application/json') self.assertEqual(status.HTTP_404_NOT_FOUND, response.status_code) self.assertEqual("application/json", response.mimetype)
def test_get_session_collection_when_is_empty(self, _, __): """Tests get Session Collection when active session list is empty""" with open('oneview_redfish_toolkit/mockups/redfish/' 'SessionCollectionEmpty.json') as f: expected_session_collection = json.load(f) client_session.init_map_clients() response = self.client.get("/redfish/v1/SessionService/Sessions", content_type='application/json') result = json.loads(response.data.decode("utf-8")) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual("application/json", response.mimetype) self.assertEqualMockup(expected_session_collection, result)
def test_post_session_with_login_domain_data(self, get_authentication_mode, oneview_client_mockup, uuid_mock): """Tests post Session when UserName has login domain information""" with open('oneview_redfish_toolkit/mockups/redfish/' 'SessionForLoginWithDomain.json') as f: expected_session_mockup = json.load(f) client_session.init_map_clients() multiple_oneview.init_map_appliances() get_authentication_mode.return_value = 'session' # Create mock response uuid_mock.uuid4.return_value = self.session_id oneview_client = oneview_client_mockup() oneview_client.connection.get_session_id.return_value = self.token_id # POST Session response = self.client.post("/redfish/v1/SessionService/Sessions", data=json.dumps( dict(UserName="******", Password="******")), content_type='application/json') # Gets json from response result = json.loads(response.data.decode("utf-8")) # Tests response self.assertEqual(status.HTTP_201_CREATED, response.status_code) self.assertEqual("application/json", response.mimetype) self.assertEqualMockup(expected_session_mockup, result) self.assertIn("/redfish/v1/SessionService/Sessions/" + self.session_id, response.headers["Location"]) self.assertEqual(self.token_id, response.headers["X-Auth-Token"]) oneview_client_mockup.assert_called_with({ 'ip': config.get_oneview_multiple_ips()[0], 'credentials': { 'userName': '******', 'password': '******', 'authLoginDomain': 'LOCAL' }, 'api_version': config.get_api_version() })
def test_get_session(self, _, uuid_mock): """Tests get a specific Session""" with open('oneview_redfish_toolkit/mockups/redfish/Session.json') as f: expected_session = json.load(f) uuid_mock.uuid4.side_effect = self.session_ids client_session.init_map_clients() client_session._set_new_client_by_token('abc', '10.0.0.1') client_session._set_new_client_by_token('def', '10.0.0.2') response = self.client.get("/redfish/v1/SessionService/Sessions/" + expected_session["Id"], content_type='application/json') result = json.loads(response.data.decode("utf-8")) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual("application/json", response.mimetype) self.assertEqualMockup(expected_session, result)
def test_post_many_sessions(self, oneview_client_mockup, uuid_mock): """Tests post many Sessions and gets them""" with open('oneview_redfish_toolkit/mockups/redfish/' 'SessionCollection.json') as f: expected_session_collection = json.load(f) client_session.init_map_clients() multiple_oneview.init_map_appliances() session_ids = self.session_ids uuid_mock.uuid4.side_effect = session_ids oneview_client = oneview_client_mockup() oneview_client.connection.get_session_id.side_effect = [ 'abc', 'def', 'ghi' ] self.client.post("/redfish/v1/SessionService/Sessions", data=json.dumps( dict(UserName="******", Password="******")), content_type='application/json') self.client.post("/redfish/v1/SessionService/Sessions", data=json.dumps( dict(UserName="******", Password="******")), content_type='application/json') self.client.post("/redfish/v1/SessionService/Sessions", data=json.dumps( dict(UserName="******", Password="******")), content_type='application/json') response = self.client.get('/redfish/v1/SessionService/Sessions', content_type='application/json') result = json.loads(response.data.decode("utf-8")) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(expected_session_collection, result)
def setUp(self): client_session.init_map_clients() multiple_oneview.init_map_appliances()
def main(config_file_path, logging_config_file_path, is_dev_env=False, is_debug_mode=False): # Load config file, schemas and creates a OV connection try: config.configure_logging(logging_config_file_path) config.load_config(config_file_path) except Exception as e: logging.exception('Failed to load app configuration') logging.exception(e) exit(1) # Check auth mode auth_mode = config.get_authentication_mode() if auth_mode not in ["conf", "session"]: logging.error("Invalid authentication_mode. Please check your conf" " file. Valid values are 'conf' or 'session'") # Flask application app = Flask(__name__) app.url_map.strict_slashes = False # Register blueprints app.register_blueprint(redfish_base, url_prefix="/redfish/") app.register_blueprint(service_root, url_prefix='/redfish/v1/') app.register_blueprint(event_service) app.register_blueprint(session_service) app.register_blueprint(chassis_collection) app.register_blueprint(computer_system_collection) app.register_blueprint(computer_system) app.register_blueprint(composition_service) app.register_blueprint(chassis) app.register_blueprint(ethernet_interface) app.register_blueprint(ethernet_interface_collection) app.register_blueprint(manager_collection) app.register_blueprint(manager) app.register_blueprint(metadata) app.register_blueprint(odata) app.register_blueprint(storage) app.register_blueprint(thermal) app.register_blueprint(storage_collection) app.register_blueprint(network_adapter_collection) app.register_blueprint(network_interface_collection) app.register_blueprint(network_port_collection) app.register_blueprint(network_device_function_collection) app.register_blueprint(network_device_function) app.register_blueprint(network_interface) app.register_blueprint(network_adapter) app.register_blueprint(network_port) app.register_blueprint(processor) app.register_blueprint(processor_collection) app.register_blueprint(storage_for_resource_block) app.register_blueprint(resource_block_collection) app.register_blueprint(resource_block) app.register_blueprint(vlan_network_interface) app.register_blueprint(zone_collection) app.register_blueprint(zone) # Init cached data client_session.init_map_clients() client_session.init_gc_for_expired_sessions() multiple_oneview.init_map_resources() multiple_oneview.init_map_appliances() category_resource.init_map_category_resources() if auth_mode == "conf": app.register_blueprint(subscription_collection) app.register_blueprint(subscription) client_session.login_conf_mode() else: app.register_blueprint(session) @app.before_request def init_performance_data(): if logging.getLogger().isEnabledFor(logging.DEBUG): g.start_time_req = time.time() g.elapsed_time_ov = 0 @app.before_request def check_authentication(): # If authenticating do not check for anything if request.url_rule and \ request.url_rule.rule == SessionCollection.BASE_URI and \ request.method == "POST": return None if connection.is_service_root(): return None if config.auth_mode_is_session(): x_auth_token = request.headers.get('x-auth-token') client_session.check_authentication(x_auth_token) g.oneview_client = \ handler_multiple_oneview.MultipleOneViewResource() @app.before_request def has_odata_version_header(): """Deny request that specify a different OData-Version than 4.0""" odata_version_header = request.headers.get("OData-Version") if odata_version_header is None: pass elif odata_version_header != "4.0": abort( status.HTTP_412_PRECONDITION_FAILED, "The request specify a different OData-Version " "header then 4.0. This server also responds " "to requests without the OData-Version header") @app.after_request def set_odata_version_header(response): """Set OData-Version header for all responses""" response.headers["OData-Version"] = "4.0" return response @app.after_request def log_performance_data(response): if logging.getLogger().isEnabledFor(logging.DEBUG): end_time = time.time() req_time = end_time - g.start_time_req logging.getLogger(PERFORMANCE_LOGGER_NAME).debug( "OneView process: " + str(g.elapsed_time_ov)) logging.getLogger(PERFORMANCE_LOGGER_NAME).debug( "Redfish process: " + str(req_time - g.elapsed_time_ov)) logging.getLogger(PERFORMANCE_LOGGER_NAME).debug( "Total process: " + str(req_time)) return response @app.errorhandler(status.HTTP_400_BAD_REQUEST) def bad_request(error): """Creates a Bad Request Error response""" logging.error(error.description) return ResponseBuilder.error_400(error) @app.errorhandler(status.HTTP_401_UNAUTHORIZED) def unauthorized_error(error): """Creates a Unauthorized Error response""" logging.error(error.description) return ResponseBuilder.error_401(error) @app.errorhandler(status.HTTP_403_FORBIDDEN) def forbidden(error): """Creates a Forbidden Error response""" logging.error(error.description) return ResponseBuilder.error_403(error) @app.errorhandler(status.HTTP_404_NOT_FOUND) def not_found(error): """Creates a Not Found Error response""" logging.error(error.description) return ResponseBuilder.error_404(error) @app.errorhandler(status.HTTP_500_INTERNAL_SERVER_ERROR) def internal_server_error(error): """Creates an Internal Server Error response""" logging.error(error) return ResponseBuilder.error_500(error) @app.errorhandler(status.HTTP_501_NOT_IMPLEMENTED) def not_implemented(error): """Creates a Not Implemented Error response""" logging.error(error.description) return ResponseBuilder.error_501(error) @app.errorhandler(HPOneViewException) def hp_oneview_client_exception(exception): logging.exception(exception) response = ResponseBuilder.error_by_hp_oneview_exception(exception) # checking if session has expired on Oneview if config.auth_mode_is_session() and \ response.status_code == status.HTTP_401_UNAUTHORIZED: token = request.headers.get('x-auth-token') client_session.clear_session_by_token(token) return response @app.errorhandler(OneViewRedfishException) def oneview_redfish_exception(exception): logging.exception(exception) return ResponseBuilder.oneview_redfish_exception(exception) scmb.init_event_service() app_config = config.get_config() try: host = app_config["redfish"]["redfish_host"] # Gets the correct IP type based on the string ipaddress.ip_address(host) except ValueError: logging.error("Informed IP is not valid. Check the " "variable 'redfish_host' on your config file.") exit(1) try: port = int(app_config["redfish"]["redfish_port"]) except Exception: logging.exception( "Port must be an integer number between 1 and 65536.") exit(1) # Checking port range if port < 1 or port > 65536: logging.error("Port must be an integer number between 1 and 65536.") exit(1) if app_config["ssl"]["SSLType"] in ("self-signed", "adhoc"): logging.warning("Server is starting with a self-signed certificate.") if app_config["ssl"]["SSLType"] == "disabled": logging.warning( "Server is starting in HTTP mode. This is an insecure mode. " "Running the server with HTTPS enabled is highly recommended.") ssl_type = app_config["ssl"]["SSLType"] # Check SSLType: if ssl_type not in ('disabled', 'adhoc', 'certs', 'self-signed'): logging.error("Invalid SSL type: {}. Must be one of: disabled, adhoc, " "self-signed or certs".format(ssl_type)) exit(1) if ssl_type == 'disabled': app.run(host=host, port=port, debug=is_debug_mode) elif ssl_type == 'adhoc': app.run(host=host, port=port, debug=is_debug_mode, ssl_context="adhoc") else: # We should use certs file provided by the user ssl_cert_file = app_config["ssl"]["SSLCertFile"] ssl_key_file = app_config["ssl"]["SSLKeyFile"] # Generating cert files if they don't exists if ssl_type == "self-signed": if not os.path.exists(ssl_cert_file) and not \ os.path.exists(ssl_key_file): logging.warning("Generating self-signed certs") # Generate certificates util.generate_certificate(os.path.dirname(ssl_cert_file), "self-signed", 2048) else: logging.warning("Using existing self-signed certs") elif ssl_cert_file == "" or ssl_key_file == "": logging.error( "SSL type: is 'cert' but one of the files are missing on" "the config file. SSLCertFile: {}, SSLKeyFile: {}.".format( ssl_cert_file, ssl_key_file)) if is_dev_env and is_debug_mode: ssl_context = (ssl_cert_file, ssl_key_file) app.run(host=host, port=port, debug=is_debug_mode, ssl_context=ssl_context) else: start_cherrypy(app, host=host, port=port, ssl_cert_file=ssl_cert_file, ssl_key_file=ssl_key_file, is_dev_env=is_dev_env)