def put_metric_data(self, req): """ Implements PutMetricData API action """ con = req.context parms = dict(req.params) namespace = api_utils.get_param_value(parms, 'Namespace') # Extract data from the request so we can pass it to the engine # We have to do this in two passes, because the AWS # query format nests the dimensions within the MetricData # query-parameter-list (see AWS PutMetricData docs) # extract_param_list gives a list-of-dict, which we then # need to process (each dict) for dimensions metric_data = api_utils.extract_param_list(parms, prefix='MetricData') if not len(metric_data): logger.error("Request does not contain required MetricData") return exception.HeatMissingParameterError("MetricData list") watch_name = None dimensions = [] for p in metric_data: dimension = api_utils.extract_param_pairs(p, prefix='Dimensions', keyname='Name', valuename='Value') if 'AlarmName' in dimension: watch_name = dimension['AlarmName'] else: dimensions.append(dimension) # We expect an AlarmName dimension as currently the engine # implementation requires metric data to be associated # with an alarm. When this is fixed, we can simply # parse the user-defined dimensions and add the list to # the metric data if not watch_name: logger.error("Request does not contain AlarmName dimension!") return exception.HeatMissingParameterError("AlarmName dimension") # Extract the required data from the metric_data # and format dict to pass to engine data = { 'Namespace': namespace, api_utils.get_param_value(metric_data[0], 'MetricName'): { 'Unit': api_utils.get_param_value(metric_data[0], 'Unit'), 'Value': api_utils.get_param_value(metric_data[0], 'Value'), 'Dimensions': dimensions } } try: self.engine_rpcapi.create_watch_data(con, watch_name, data) except rpc_common.RemoteError as ex: return exception.map_remote_error(ex) result = {'ResponseMetadata': None} return api_utils.format_response("PutMetricData", result)
def test_extract_param_list_garbage_prefix2(self): p = { 'AMetricData.member.1.MetricName': 'foo', 'BMetricData.member.1.Unit': 'Bytes', 'CMetricData.member.1.Value': 234333 } params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(0, len(params))
def test_extract_param_list_garbage_prefix2(self): p = { "AMetricData.member.1.MetricName": "foo", "BMetricData.member.1.Unit": "Bytes", "CMetricData.member.1.Value": 234333, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(len(params), 0)
def put_metric_data(self, req): """ Implements PutMetricData API action """ self._enforce(req, 'PutMetricData') con = req.context parms = dict(req.params) namespace = api_utils.get_param_value(parms, 'Namespace') # Extract data from the request so we can pass it to the engine # We have to do this in two passes, because the AWS # query format nests the dimensions within the MetricData # query-parameter-list (see AWS PutMetricData docs) # extract_param_list gives a list-of-dict, which we then # need to process (each dict) for dimensions metric_data = api_utils.extract_param_list(parms, prefix='MetricData') if not len(metric_data): logger.error("Request does not contain required MetricData") return exception.HeatMissingParameterError("MetricData list") watch_name = None dimensions = [] for p in metric_data: dimension = api_utils.extract_param_pairs(p, prefix='Dimensions', keyname='Name', valuename='Value') if 'AlarmName' in dimension: watch_name = dimension['AlarmName'] else: dimensions.append(dimension) # We expect an AlarmName dimension as currently the engine # implementation requires metric data to be associated # with an alarm. When this is fixed, we can simply # parse the user-defined dimensions and add the list to # the metric data if not watch_name: logger.error("Request does not contain AlarmName dimension!") return exception.HeatMissingParameterError("AlarmName dimension") # Extract the required data from the metric_data # and format dict to pass to engine data = {'Namespace': namespace, api_utils.get_param_value(metric_data[0], 'MetricName'): { 'Unit': api_utils.get_param_value(metric_data[0], 'Unit'), 'Value': api_utils.get_param_value(metric_data[0], 'Value'), 'Dimensions': dimensions}} try: self.engine_rpcapi.create_watch_data(con, watch_name, data) except rpc_common.RemoteError as ex: return exception.map_remote_error(ex) result = {'ResponseMetadata': None} return api_utils.format_response("PutMetricData", result)
def test_extract_param_list_badindex(self): p = {'MetricData.member.xyz.MetricName': 'foo', 'MetricData.member.$!&^.Unit': 'Bytes', 'MetricData.member.+.Value': 234333, 'MetricData.member.--.MetricName': 'foo2', 'MetricData.member._3.Unit': 'Bytes', 'MetricData.member.-1000.Value': 12345} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(len(params), 0)
def test_extract_param_list_garbage_prefix(self): p = {'AMetricData.member.1.MetricName': 'foo', 'MetricData.member.1.Unit': 'Bytes', 'MetricData.member.1.Value': 234333} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(1, len(params)) self.assertNotIn('MetricName', params[0]) self.assertIn('Unit', params[0]) self.assertIn('Value', params[0]) self.assertEqual('Bytes', params[0]['Unit']) self.assertEqual(234333, params[0]['Value'])
def test_extract_param_list_badindex(self): p = { "MetricData.member.xyz.MetricName": "foo", "MetricData.member.$!&^.Unit": "Bytes", "MetricData.member.+.Value": 234333, "MetricData.member.--.MetricName": "foo2", "MetricData.member._3.Unit": "Bytes", "MetricData.member.-1000.Value": 12345, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(len(params), 0)
def test_extract_param_list_garbage_prefix(self): p = {'AMetricData.member.1.MetricName': 'foo', 'MetricData.member.1.Unit': 'Bytes', 'MetricData.member.1.Value': 234333} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(len(params), 1) self.assertTrue('MetricName' not in params[0]) self.assertTrue('Unit' in params[0]) self.assertTrue('Value' in params[0]) self.assertEqual(params[0]['Unit'], 'Bytes') self.assertEqual(params[0]['Value'], 234333)
def test_extract_param_list_garbage_suffix(self): p = { "MetricData.member.1.AMetricName": "foo", "MetricData.member.1.Unit": "Bytes", "MetricData.member.1.Value": 234333, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(len(params), 1) self.assertNotIn("MetricName", params[0]) self.assertIn("Unit", params[0]) self.assertIn("Value", params[0]) self.assertEqual(params[0]["Unit"], "Bytes") self.assertEqual(params[0]["Value"], 234333)
def put_metric_data(self, req): """ Implements PutMetricData API action """ self._enforce(req, 'PutMetricData') con = req.context parms = dict(req.params) namespace = api_utils.get_param_value(parms, 'Namespace') # Extract data from the request so we can pass it to the engine # We have to do this in two passes, because the AWS # query format nests the dimensions within the MetricData # query-parameter-list (see AWS PutMetricData docs) # extract_param_list gives a list-of-dict, which we then # need to process (each dict) for dimensions metric_data = api_utils.extract_param_list(parms, prefix='MetricData') if not len(metric_data): LOG.error(_LE("Request does not contain required MetricData")) return exception.HeatMissingParameterError("MetricData list") watch_name = None dimensions = [] for p in metric_data: dimension = api_utils.extract_param_pairs(p, prefix='Dimensions', keyname='Name', valuename='Value') if 'AlarmName' in dimension: watch_name = dimension['AlarmName'] else: dimensions.append(dimension) # Extract the required data from the metric_data # and format dict to pass to engine data = { 'Namespace': namespace, api_utils.get_param_value(metric_data[0], 'MetricName'): { 'Unit': api_utils.get_param_value(metric_data[0], 'Unit'), 'Value': api_utils.get_param_value(metric_data[0], 'Value'), 'Dimensions': dimensions } } try: self.rpc_client.create_watch_data(con, watch_name, data) except messaging.RemoteError as ex: return exception.map_remote_error(ex) result = {'ResponseMetadata': None} return api_utils.format_response("PutMetricData", result)
def test_extract_param_list(self): p = { "MetricData.member.1.MetricName": "foo", "MetricData.member.1.Unit": "Bytes", "MetricData.member.1.Value": 234333, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(1, len(params)) self.assertIn("MetricName", params[0]) self.assertIn("Unit", params[0]) self.assertIn("Value", params[0]) self.assertEqual("foo", params[0]["MetricName"]) self.assertEqual("Bytes", params[0]["Unit"]) self.assertEqual(234333, params[0]["Value"])
def put_metric_data(self, req): """ Implements PutMetricData API action """ self._enforce(req, "PutMetricData") con = req.context parms = dict(req.params) namespace = api_utils.get_param_value(parms, "Namespace") # Extract data from the request so we can pass it to the engine # We have to do this in two passes, because the AWS # query format nests the dimensions within the MetricData # query-parameter-list (see AWS PutMetricData docs) # extract_param_list gives a list-of-dict, which we then # need to process (each dict) for dimensions metric_data = api_utils.extract_param_list(parms, prefix="MetricData") if not len(metric_data): logger.error(_("Request does not contain required MetricData")) return exception.HeatMissingParameterError("MetricData list") watch_name = None dimensions = [] for p in metric_data: dimension = api_utils.extract_param_pairs(p, prefix="Dimensions", keyname="Name", valuename="Value") if "AlarmName" in dimension: watch_name = dimension["AlarmName"] else: dimensions.append(dimension) # Extract the required data from the metric_data # and format dict to pass to engine data = { "Namespace": namespace, api_utils.get_param_value(metric_data[0], "MetricName"): { "Unit": api_utils.get_param_value(metric_data[0], "Unit"), "Value": api_utils.get_param_value(metric_data[0], "Value"), "Dimensions": dimensions, }, } try: self.rpc_client.create_watch_data(con, watch_name, data) except rpc_common.RemoteError as ex: return exception.map_remote_error(ex) result = {"ResponseMetadata": None} return api_utils.format_response("PutMetricData", result)
def test_extract_param_list_multiple(self): p = {'MetricData.member.1.MetricName': 'foo', 'MetricData.member.1.Unit': 'Bytes', 'MetricData.member.1.Value': 234333, 'MetricData.member.2.MetricName': 'foo2', 'MetricData.member.2.Unit': 'Bytes', 'MetricData.member.2.Value': 12345} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(len(params), 2) self.assertTrue('MetricName' in params[0]) self.assertTrue('MetricName' in params[1]) self.assertEqual(params[0]['MetricName'], 'foo') self.assertEqual(params[0]['Unit'], 'Bytes') self.assertEqual(params[0]['Value'], 234333) self.assertEqual(params[1]['MetricName'], 'foo2') self.assertEqual(params[1]['Unit'], 'Bytes') self.assertEqual(params[1]['Value'], 12345)
def test_extract_param_list_multiple(self): p = {'MetricData.member.1.MetricName': 'foo', 'MetricData.member.1.Unit': 'Bytes', 'MetricData.member.1.Value': 234333, 'MetricData.member.2.MetricName': 'foo2', 'MetricData.member.2.Unit': 'Bytes', 'MetricData.member.2.Value': 12345} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(2, len(params)) self.assertIn('MetricName', params[0]) self.assertIn('MetricName', params[1]) self.assertEqual('foo', params[0]['MetricName']) self.assertEqual('Bytes', params[0]['Unit']) self.assertEqual(234333, params[0]['Value']) self.assertEqual('foo2', params[1]['MetricName']) self.assertEqual('Bytes', params[1]['Unit']) self.assertEqual(12345, params[1]['Value'])
def test_extract_param_list_multiple_missing(self): # Handle case where there is an empty list item p = {'MetricData.member.1.MetricName': 'foo', 'MetricData.member.1.Unit': 'Bytes', 'MetricData.member.1.Value': 234333, 'MetricData.member.3.MetricName': 'foo2', 'MetricData.member.3.Unit': 'Bytes', 'MetricData.member.3.Value': 12345} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(len(params), 2) self.assertTrue('MetricName' in params[0]) self.assertTrue('MetricName' in params[1]) self.assertEqual(params[0]['MetricName'], 'foo') self.assertEqual(params[0]['Unit'], 'Bytes') self.assertEqual(params[0]['Value'], 234333) self.assertEqual(params[1]['MetricName'], 'foo2') self.assertEqual(params[1]['Unit'], 'Bytes') self.assertEqual(params[1]['Value'], 12345)
def test_extract_param_list_multiple(self): p = { "MetricData.member.1.MetricName": "foo", "MetricData.member.1.Unit": "Bytes", "MetricData.member.1.Value": 234333, "MetricData.member.2.MetricName": "foo2", "MetricData.member.2.Unit": "Bytes", "MetricData.member.2.Value": 12345, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(len(params), 2) self.assertIn("MetricName", params[0]) self.assertIn("MetricName", params[1]) self.assertEqual(params[0]["MetricName"], "foo") self.assertEqual(params[0]["Unit"], "Bytes") self.assertEqual(params[0]["Value"], 234333) self.assertEqual(params[1]["MetricName"], "foo2") self.assertEqual(params[1]["Unit"], "Bytes") self.assertEqual(params[1]["Value"], 12345)
def test_extract_param_list_multiple_missing(self): # Handle case where there is an empty list item p = { "MetricData.member.1.MetricName": "foo", "MetricData.member.1.Unit": "Bytes", "MetricData.member.1.Value": 234333, "MetricData.member.3.MetricName": "foo2", "MetricData.member.3.Unit": "Bytes", "MetricData.member.3.Value": 12345, } params = api_utils.extract_param_list(p, prefix="MetricData") self.assertEqual(len(params), 2) self.assertIn("MetricName", params[0]) self.assertIn("MetricName", params[1]) self.assertEqual(params[0]["MetricName"], "foo") self.assertEqual(params[0]["Unit"], "Bytes") self.assertEqual(params[0]["Value"], 234333) self.assertEqual(params[1]["MetricName"], "foo2") self.assertEqual(params[1]["Unit"], "Bytes") self.assertEqual(params[1]["Value"], 12345)
def test_extract_param_list_garbage_prefix2(self): p = {'AMetricData.member.1.MetricName': 'foo', 'BMetricData.member.1.Unit': 'Bytes', 'CMetricData.member.1.Value': 234333} params = api_utils.extract_param_list(p, prefix='MetricData') self.assertEqual(len(params), 0)