raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 1 | import sys, getopt |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 2 | import socket |
| 3 | import requests |
| 4 | import urllib2 |
| 5 | import json |
| 6 | import msgpack |
| 7 | import collections |
| 8 | import time, thread, threading |
| 9 | |
| 10 | from flask import request, Request, jsonify |
| 11 | from flask import Flask |
| 12 | from flask import make_response |
| 13 | app = Flask(__name__) |
| 14 | |
| 15 | projects_map = {} |
| 16 | xos_tenant_info_map = {} |
| 17 | xos_instances_info_map = {} |
| 18 | |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 19 | #gethostname() -- return the current hostname |
| 20 | #gethostbyname() -- map a hostname to its IP number |
| 21 | hostname = None |
| 22 | xos_ip = None |
| 23 | kafka_ip = xos_ip |
| 24 | xos_port = 9000 |
| 25 | |
| 26 | print "----------------------------------------------------------------------" |
| 27 | print "xos_ip:",xos_ip |
| 28 | print "kfka_ip:",kafka_ip |
| 29 | print "----------------------------------------------------------------------" |
| 30 | |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 31 | use_kafka = True |
| 32 | |
| 33 | if use_kafka: |
| 34 | import kafka |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 35 | import kafka_broker |
| 36 | from oslo_utils import netutils |
| 37 | #from kafka import TopicPartition |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 38 | else: |
| 39 | UDP_IP = "0.0.0.0" |
| 40 | UDP_PORT = 12346 |
| 41 | |
| 42 | @app.route('/autoscaledata',methods=['GET']) |
| 43 | def autoscaledata(): |
| 44 | response = app.make_response(json.dumps(projects_map.values())) |
| 45 | response.mimetype="application/json" |
| 46 | return response |
| 47 | |
| 48 | def acquire_xos_monitoring_channel(): |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 49 | global xos_ip |
| 50 | |
| 51 | url = "http://" + xos_ip + ":" + str(xos_port) +"/api/tenant/monitoring/monitoringchannel/" |
| 52 | print url |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 53 | admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password |
| 54 | monitoring_channels = requests.get(url, auth=admin_auth).json() |
| 55 | ceilometer_url = None |
| 56 | if not monitoring_channels: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 57 | print 'No monitoring channels for this user...' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 58 | return None |
| 59 | else: |
| 60 | monitoring_channel = monitoring_channels[0] |
| 61 | while not monitoring_channel['ceilometer_url']: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 62 | print 'Waiting for monitoring channel create' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 63 | sleep(0.5) |
| 64 | monitoring_channel = requests.get(url, auth=admin_auth).json()[0] |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 65 | while True: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 66 | print 'Waiting for ceilometer proxy URL %s is available' % monitoring_channel['ceilometer_url'] |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 67 | try: |
| 68 | response = urllib2.urlopen(monitoring_channel['ceilometer_url'],timeout=1) |
| 69 | break |
| 70 | except urllib2.HTTPError, e: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 71 | print 'HTTP error %s' % e.reason |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 72 | break |
| 73 | except urllib2.URLError, e: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 74 | print 'URL error %s' % e.reason |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 75 | pass |
| 76 | return monitoring_channel |
| 77 | |
| 78 | def print_samples(): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 79 | global supported_services |
| 80 | |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 81 | print "" |
| 82 | print "" |
| 83 | for project in projects_map.keys(): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 84 | xos_service = projects_map[project]['service'] |
| 85 | if (not xos_service) or (xos_service not in supported_services): |
| 86 | print "Skipped scale evaluation for project=%s and service =%s" % (project, xos_service) |
| 87 | continue |
| 88 | print "service=%s slice=%s, alarm_state=%s lcount=%s ucount=%s" % (projects_map[project]['service'], projects_map[project]['slice'] if projects_map[project]['slice'] else project, projects_map[project]['alarm'], projects_map[project]['lthreadshold_count'], projects_map[project]['uthreadshold_count']) |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 89 | for resource in projects_map[project]['resources'].keys(): |
| 90 | print "resource=%s" % (projects_map[project]['resources'][resource]['xos_instance_info']['instance_name'] if projects_map[project]['resources'][resource]['xos_instance_info'] else resource) |
| 91 | for i in projects_map[project]['resources'][resource]['queue']: |
| 92 | print " time=%s val=%s" % ( i['timestamp'],i['counter_volume']) |
| 93 | |
| 94 | def periodic_print(): |
| 95 | print_samples() |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 96 | #Print every 20 seconds |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 97 | threading.Timer(20, periodic_print).start() |
| 98 | |
| 99 | |
| 100 | CPU_UPPER_THRESHOLD = 80 #80% |
| 101 | CPU_LOWER_THRESHOLD = 30 #30% |
| 102 | CPU_THRESHOLD_REPEAT = 3 |
| 103 | INITIAL_STATE = 'normal_config' |
| 104 | SCALE_UP_EVALUATION = 'scale_up_eval' |
| 105 | SCALE_DOWN_EVALUATION = 'scale_down_eval' |
| 106 | SCALE_UP_ALARM = 'scale_up' |
| 107 | SCALE_DOWN_ALARM = 'scale_down' |
| 108 | |
| 109 | def loadAllXosTenantInfo(): |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 110 | global xos_ip |
| 111 | |
| 112 | print "Loading all XOS tenant info" |
| 113 | url = "http://" + xos_ip + ":" + str(xos_port) +"/xos/controllerslices/" |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 114 | admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password |
| 115 | controller_slices = requests.get(url, auth=admin_auth).json() |
| 116 | for cslice in controller_slices: |
| 117 | slice = requests.get(cslice['slice'], auth=admin_auth).json() |
| 118 | slice_name = slice['humanReadableName'] |
| 119 | if slice['service']: |
| 120 | service = requests.get(slice['service'], auth=admin_auth).json() |
| 121 | service_name = service['humanReadableName'] |
| 122 | else: |
| 123 | service_name = None |
| 124 | xos_tenant_info_map[cslice['tenant_id']] = {'service':service_name, 'slice':slice_name} |
| 125 | print "SRIKANTH: Project: %s Service:%s Slice:%s" % (cslice['tenant_id'],service_name,slice_name) |
| 126 | |
| 127 | def loadAllXosInstanceInfo(): |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 128 | global xos_ip |
| 129 | |
| 130 | print "Loading all XOS instance info" |
| 131 | url = "http://" + xos_ip + ":" + str(xos_port) +"/xos/instances/" |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 132 | admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password |
| 133 | xos_instances = requests.get(url, auth=admin_auth).json() |
| 134 | for instance in xos_instances: |
| 135 | xos_instances_info_map[instance['instance_uuid']] = {'instance_name':instance['instance_name']} |
| 136 | |
| 137 | def getXosTenantInfo(project): |
| 138 | xos_tenant_info = xos_tenant_info_map.get(project, None) |
| 139 | if xos_tenant_info: |
| 140 | return xos_tenant_info |
| 141 | else: |
| 142 | loadAllXosTenantInfo() |
| 143 | xos_tenant_info = xos_tenant_info_map.get(project, None) |
| 144 | if not xos_tenant_info: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 145 | print "Project %s has no associated XOS slice" % project |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 146 | return xos_tenant_info |
| 147 | |
| 148 | def getXosInstanceInfo(resource): |
| 149 | xos_instance_info = xos_instances_info_map.get(resource, None) |
| 150 | if xos_instance_info: |
| 151 | return xos_instance_info |
| 152 | else: |
| 153 | loadAllXosInstanceInfo() |
| 154 | xos_instance_info = xos_instances_info_map.get(resource, None) |
| 155 | if not xos_instance_info: |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 156 | print "Resource %s has no associated XOS instance" % resource |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 157 | return xos_instance_info |
| 158 | |
| 159 | def handle_adjust_scale(project, adjust): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 160 | global xos_ip, supported_services |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 161 | |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 162 | if (adjust != 'up') and (adjust != 'down'): |
| 163 | print "SRIKANTH: Invalid adjust value %s " % adjust |
| 164 | return |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 165 | xos_service = projects_map[project]['service'] |
| 166 | xos_slice = projects_map[project]['slice'] |
| 167 | if not xos_service or not xos_slice: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 168 | print "Can not handle adjust_scale for Project %s because not associated with any service or slice" % project |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 169 | return |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 170 | if (xos_service not in supported_services): |
| 171 | print "SRIKANTH: Scaling is not supported for this service %s...Ignoring adjust_scale request" % xos_service |
| 172 | return |
| 173 | current_instances = len(projects_map[project]['resources'].keys()) |
| 174 | if (current_instances <=1 and adjust == 'down'): |
| 175 | print "%s is running with already minimum instances and can not scale down further " % xos_service |
| 176 | return |
| 177 | if (current_instances >=2 and adjust == 'up'): |
| 178 | print "%s is running with already maximum instances and can not scale up further " % xos_service |
| 179 | return |
| 180 | #xos_tenant = getXosTenantInfo(project) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 181 | print "SCALE %s for Project %s, Slice=%s, Service=%s from current=%d to new=%d" % (adjust, project, xos_slice, xos_service, current_instances, current_instances+1 if (adjust=='up') else current_instances-1) |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 182 | query_params = {'service':xos_service, 'slice_hint':xos_slice, 'scale':current_instances+1 if (adjust=='up') else current_instances-1} |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 183 | url = "http://" + xos_ip + ":" + str(xos_port) + "/api/tenant/monitoring/dashboard/serviceadjustscale/" |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 184 | admin_auth=("padmin@vicci.org", "letmein") # use your XOS username and password |
| 185 | response = requests.get(url, params=query_params, auth=admin_auth).json() |
| 186 | print "SRIKANTH: XOS adjust_scale response: %s" % response |
| 187 | |
| 188 | def periodic_cpu_threshold_evaluator(): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 189 | global supported_services |
| 190 | |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 191 | for project in projects_map.keys(): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 192 | xos_service = projects_map[project]['service'] |
| 193 | if (not xos_service) or (xos_service not in supported_services): |
| 194 | #print "Skipping scale evaluation for project=%s and service =%s" % (project, xos_service) |
| 195 | continue |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 196 | aggregate_cpu_util = sum([resource['queue'][-1]['counter_volume'] \ |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 197 | for resource in projects_map[project]['resources'].values() if 'queue' in resource.keys()]) \ |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 198 | /len(projects_map[project]['resources'].keys()) |
| 199 | |
| 200 | if (projects_map[project]['alarm'] == INITIAL_STATE or |
| 201 | projects_map[project]['alarm'] == SCALE_UP_ALARM or |
| 202 | projects_map[project]['alarm'] == SCALE_DOWN_ALARM): |
| 203 | if aggregate_cpu_util > CPU_UPPER_THRESHOLD: |
| 204 | projects_map[project]['uthreadshold_count'] = 1 |
| 205 | projects_map[project]['alarm'] = SCALE_UP_EVALUATION |
| 206 | if projects_map[project]['uthreadshold_count'] >= CPU_THRESHOLD_REPEAT: |
| 207 | projects_map[project]['alarm'] = SCALE_UP_ALARM |
| 208 | handle_adjust_scale(project, 'up') |
| 209 | elif aggregate_cpu_util < CPU_LOWER_THRESHOLD: |
| 210 | projects_map[project]['lthreadshold_count'] = 1 |
| 211 | projects_map[project]['alarm'] = SCALE_DOWN_EVALUATION |
| 212 | if projects_map[project]['lthreadshold_count'] >= CPU_THRESHOLD_REPEAT: |
| 213 | projects_map[project]['alarm'] = SCALE_DOWN_ALARM |
| 214 | handle_adjust_scale(project, 'down') |
| 215 | else: |
| 216 | projects_map[project]['uthreadshold_count'] = 0 |
| 217 | projects_map[project]['lthreadshold_count'] = 0 |
| 218 | projects_map[project]['alarm'] = INITIAL_STATE |
| 219 | elif projects_map[project]['alarm'] == SCALE_UP_EVALUATION: |
| 220 | if aggregate_cpu_util > CPU_UPPER_THRESHOLD: |
| 221 | projects_map[project]['uthreadshold_count'] += 1 |
| 222 | if projects_map[project]['uthreadshold_count'] >= CPU_THRESHOLD_REPEAT: |
| 223 | projects_map[project]['alarm'] = SCALE_UP_ALARM |
| 224 | handle_adjust_scale(project, 'up') |
| 225 | elif aggregate_cpu_util < CPU_LOWER_THRESHOLD: |
| 226 | projects_map[project]['lthreadshold_count'] += 1 |
| 227 | projects_map[project]['alarm'] = SCALE_DOWN_EVALUATION |
| 228 | else: |
| 229 | projects_map[project]['uthreadshold_count'] = 0 |
| 230 | projects_map[project]['alarm'] = INITIAL_STATE |
| 231 | elif projects_map[project]['alarm'] == SCALE_DOWN_EVALUATION: |
| 232 | if aggregate_cpu_util < CPU_LOWER_THRESHOLD: |
| 233 | projects_map[project]['lthreadshold_count'] += 1 |
| 234 | if projects_map[project]['lthreadshold_count'] >= CPU_THRESHOLD_REPEAT: |
| 235 | projects_map[project]['alarm'] = SCALE_DOWN_ALARM |
| 236 | handle_adjust_scale(project, 'down') |
| 237 | elif aggregate_cpu_util > CPU_UPPER_THRESHOLD: |
| 238 | projects_map[project]['uthreadshold_count'] += 1 |
| 239 | projects_map[project]['alarm'] = SCALE_UP_EVALUATION |
| 240 | else: |
| 241 | projects_map[project]['lthreadshold_count'] = 0 |
| 242 | projects_map[project]['alarm'] = INITIAL_STATE |
| 243 | threading.Timer(20, periodic_cpu_threshold_evaluator).start() |
| 244 | |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 245 | def read_notification_from_ceilometer_over_kafka(parse_target): |
| 246 | print("Kafka target:",parse_target) |
| 247 | try : |
| 248 | kafka_publisher=kafka_broker.KafkaBrokerPublisher(parse_target) |
| 249 | for message in kafka_publisher.kafka_consumer: |
| 250 | #print message.value |
| 251 | #logging.info("%s",message.value) |
| 252 | process_notification_from_ceilometer(json.loads(message.value)) |
| 253 | #print status |
| 254 | except Exception as e: |
| 255 | print "AUTO_SCALE Exception:",e |
| 256 | ''' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 257 | def read_notification_from_ceilometer_over_kafka(host,port,topic): |
| 258 | print "Kafka target" , host, port, topic |
| 259 | try : |
| 260 | consumer=kafka.KafkaConsumer(bootstrap_servers=["%s:%s" % (host,port)]) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 261 | #consumer.assign([TopicPartition(topic,0)]) |
| 262 | consumer.set_topic_partitions(topic) |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 263 | consumer.seek_to_end() |
| 264 | for message in consumer: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 265 | print message.value |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 266 | #logging.debug("%s",message.value) |
| 267 | process_notification_from_ceilometer(json.loads(message.value)) |
| 268 | #status = process_ceilometer_message(json.loads(message.value),message.value) |
| 269 | #print status |
| 270 | except Exception as e: |
| 271 | print "AUTO_SCALE Exception:",e |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 272 | ''' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 273 | |
| 274 | def read_notification_from_ceilometer(host,port): |
| 275 | udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP |
| 276 | udp.bind((host, port)) |
| 277 | |
| 278 | while True: |
| 279 | data, source = udp.recvfrom(64000) |
| 280 | try: |
| 281 | sample = msgpack.loads(data, encoding='utf-8') |
| 282 | process_notification_from_ceilometer(sample) |
| 283 | except Exception as e: |
| 284 | print e |
| 285 | |
| 286 | def process_notification_from_ceilometer(sample): |
| 287 | if sample['counter_name'] == 'instance': |
| 288 | if 'delete' in sample['resource_metadata']['event_type']: |
| 289 | xosTenantInfo = getXosTenantInfo(sample['project_id']) |
| 290 | xosResourceInfo = getXosInstanceInfo(sample['resource_id']) |
| 291 | print "SRIKANTH: Project %s Instance %s is getting deleted" % (xosTenantInfo['slice'] if xosTenantInfo['slice'] else sample['project_id'],xosResourceInfo) |
| 292 | if sample['project_id'] not in projects_map.keys(): |
| 293 | return |
| 294 | if sample['resource_id'] not in projects_map[sample['project_id']]['resources'].keys(): |
| 295 | return |
| 296 | projects_map[sample['project_id']]['resources'].pop(sample['resource_id'], None) |
| 297 | return |
| 298 | elif sample['counter_name'] != 'cpu_util': |
| 299 | return |
| 300 | if sample['project_id'] not in projects_map.keys(): |
| 301 | projects_map[sample['project_id']] = {} |
| 302 | xosTenantInfo = getXosTenantInfo(sample['project_id']) |
| 303 | projects_map[sample['project_id']]['project_id'] = sample['project_id'] |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 304 | projects_map[sample['project_id']]['slice'] = (xosTenantInfo['slice'] if xosTenantInfo else None) |
| 305 | projects_map[sample['project_id']]['service'] = (xosTenantInfo['service'] if xosTenantInfo else None) |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 306 | projects_map[sample['project_id']]['resources'] = {} |
| 307 | projects_map[sample['project_id']]['uthreadshold_count'] = 0 |
| 308 | projects_map[sample['project_id']]['lthreadshold_count'] = 0 |
| 309 | projects_map[sample['project_id']]['alarm'] = INITIAL_STATE |
| 310 | resource_map = projects_map[sample['project_id']]['resources'] |
| 311 | if sample['resource_id'] not in resource_map.keys(): |
| 312 | resource_map[sample['resource_id']] = {} |
| 313 | resource_map[sample['resource_id']]['xos_instance_info'] = getXosInstanceInfo(sample['resource_id']) |
| 314 | resource_map[sample['resource_id']]['queue'] = [] |
| 315 | samples_queue = resource_map[sample['resource_id']]['queue'] |
| 316 | sample = {'counter_name':sample['counter_name'], |
| 317 | 'project_id':sample['project_id'], |
| 318 | 'resource_id':sample['resource_id'], |
| 319 | 'timestamp':sample['timestamp'], |
| 320 | 'counter_unit':sample['counter_unit'], |
| 321 | 'counter_volume':sample['counter_volume']} |
| 322 | deque = collections.deque(samples_queue, maxlen=10) |
| 323 | deque.append(sample) |
| 324 | resource_map[sample['resource_id']]['queue'] = list(deque) |
| 325 | |
| 326 | def setup_webserver(): |
| 327 | try: |
| 328 | #config = ConfigParser.ConfigParser() |
| 329 | #config.read('pub_sub.conf') |
| 330 | #webserver_host = config.get('WEB_SERVER','webserver_host') |
| 331 | #webserver_port = int (config.get('WEB_SERVER','webserver_port')) |
| 332 | #client_host = config.get('CLIENT','client_host') |
| 333 | #client_port = int (config.get('CLIENT','client_port')) |
| 334 | |
| 335 | #log_level = config.get('LOGGING','level') |
| 336 | #log_file = config.get('LOGGING','filename') |
| 337 | |
| 338 | #level = LEVELS.get(log_level, logging.NOTSET) |
| 339 | #logging.basicConfig(filename=log_file,format='%(asctime)s %(levelname)s %(message)s',\ |
| 340 | # datefmt=_DEFAULT_LOG_DATE_FORMAT,level=level) |
| 341 | webserver_host = '0.0.0.0' |
| 342 | webserver_port = 9991 |
| 343 | |
| 344 | except Exception as e: |
| 345 | print("* Error in config file:",e.__str__()) |
| 346 | logging.error("* Error in confing file:%s",e.__str__()) |
| 347 | else: |
| 348 | app.run(host=webserver_host,port=webserver_port,debug=True, use_reloader=False) |
| 349 | |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 350 | def parse_args(argv): |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 351 | global xos_ip, kafka_ip, supported_services |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 352 | |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 353 | try: |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 354 | opts, args = getopt.getopt(argv,"k:s:x:",["kafka-ip=","supported-services=","xos-ip="]) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 355 | except getopt.GetoptError: |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 356 | print 'xos_auto_scaling_app.py --xos-ip=<IP> --kafka-ip=<> [--supported-services=<comma seperated service name>]' |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 357 | sys.exit(2) |
| 358 | |
| 359 | for opt, arg in opts: |
| 360 | if opt in ("--xos-ip"): |
| 361 | xos_ip = arg |
| 362 | elif opt in ("--kafka-ip"): |
| 363 | kafka_ip = arg |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 364 | elif opt in ("--supported-services"): |
| 365 | supported_services = arg.split(',') |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 366 | |
| 367 | if not xos_ip or not kafka_ip: |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 368 | print 'xos_auto_scaling_app.py --xos-ip=<IP> --kafka-ip=<> [--supported-services=<comma seperated service name>]' |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 369 | sys.exit(2) |
Srikanth Vavilapalli | 4812c0a | 2017-02-04 02:52:24 +0000 | [diff] [blame^] | 370 | print 'xos-ip=%s, kafka-ip=%s, supported-services=%s' % (xos_ip, kafka_ip, supported_services) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 371 | |
| 372 | |
| 373 | def main(argv): |
| 374 | global xos_ip, kafka_ip |
| 375 | |
| 376 | parse_args(argv) |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 377 | monitoring_channel = acquire_xos_monitoring_channel() |
| 378 | if not monitoring_channel: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 379 | print 'XOS monitoring_channel is not created... Create it before using this app' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 380 | return |
| 381 | loadAllXosTenantInfo() |
| 382 | loadAllXosInstanceInfo() |
| 383 | ceilometer_url = monitoring_channel['ceilometer_url'] |
| 384 | if use_kafka: |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 385 | url = "kafka://" + kafka_ip + ":9092?topic=auto-scale" |
| 386 | parse_target=netutils.urlsplit(url) |
| 387 | thread.start_new(read_notification_from_ceilometer_over_kafka, (parse_target,)) |
| 388 | #thread.start_new(read_notification_from_ceilometer_over_kafka, (xos_ip,"9092","auto-scale",)) |
| 389 | subscribe_data = {"sub_info":"cpu_util","app_id":"xos_auto_scale","target":"kafka://" + kafka_ip + ":9092?topic=auto-scale"} |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 390 | else: |
| 391 | thread.start_new(read_notification_from_ceilometer,(UDP_IP,UDP_PORT,)) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 392 | subscribe_data = {"sub_info":"cpu_util","app_id":"xos_auto_scale","target":"udp://" + xos_ip + ":12346"} |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 393 | subscribe_url = ceilometer_url + 'v2/subscribe' |
| 394 | response = requests.post(subscribe_url, data=json.dumps(subscribe_data)) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 395 | print 'Ceilometer meter "cpu_util" Subscription status:%s' % response.text |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 396 | #TODO: Fix the typo in 'sucess' |
| 397 | if (not 'sucess' in response.text) and (not 'already exists' in response.text): |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 398 | print 'Ceilometer meter "cpu_util" Subscription unsuccessful...Exiting' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 399 | return |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 400 | #TODO: Fix the need for different app_id for each subscription from the same application |
| 401 | if use_kafka: |
| 402 | subscribe_data = {"sub_info":"instance","app_id":"xos_auto_scale2","target":"kafka://" + kafka_ip + ":9092?topic=auto-scale"} |
| 403 | else: |
| 404 | subscribe_data = {"sub_info":"instance","app_id":"xos_auto_scale2","target":"udp://" + xos_ip + ":12346"} |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 405 | subscribe_url = ceilometer_url + 'v2/subscribe' |
| 406 | response = requests.post(subscribe_url, data=json.dumps(subscribe_data)) |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 407 | print 'Ceilometer meter "instance" Subscription status:%s' % response.text |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 408 | #TODO: Fix the typo in 'sucess' |
| 409 | if (not 'sucess' in response.text) and (not 'already exists' in response.text): |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 410 | print 'Ceilometer meter "instance"Subscription unsuccessful...Exiting' |
Matteo Scandolo | bf14f88 | 2016-06-02 10:01:34 -0700 | [diff] [blame] | 411 | return |
| 412 | periodic_cpu_threshold_evaluator() |
| 413 | periodic_print() |
| 414 | setup_webserver() |
| 415 | |
| 416 | if __name__ == "__main__": |
raghunath dudyala | 01482a8 | 2016-08-01 12:29:16 +0530 | [diff] [blame] | 417 | main(sys.argv[1:]) |