def ver_from_rpm_repo(self, repo, branch=None): out = {} rpm_repo_url_template = repo['rpm_repo_url'] if rpm_repo_url_template: rpm_repo_url_template = rpm_repo_url_template.strip() if branch: rpm_repo_url_template = rpm_repo_url_template % branch for release in ['5', '6']: rpm_repo_url = rpm_repo_url_template.replace( '$releasever', release) rpm_repo_url = rpm_repo_url.replace('$basearch', 'x86_64') url = os.path.join(rpm_repo_url, 'repodata/primary.xml.gz') try: r = requests.get(url) r.raise_for_status() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = 'RPM repository {0} failed, file: {1} not found'.format( repo['rpm_repo_url'], url) LOG.warning(msg) return out s = StringIO.StringIO(r.content) f = gzip.GzipFile(fileobj=s, mode='r') f.seek(0) xml = minidom.parse(f) try: out[rpm_repo_url_template] = self.rpm_pattern_1.findall( xml.toxml())[0].strip() except: out[rpm_repo_url_template] = self.rpm_pattern_2.findall( xml.toxml())[0].strip() return out
def get_metrics(host, port, key, api_type, metrics, headers=None, timeout=5): assert host, 'host' assert port, 'port' assert key, 'key' assert api_type, 'api_type' assert metrics, 'metrics' data = dict() endpoint = 'http://%s:%s' % (host, port) security = rpc.Security(key) hsp = rpc.HttpServiceProxy(endpoint, security=security, headers=headers) getters = { 'cpu': get_cpu_stat, 'la': get_la_stat, 'mem': get_mem_info, 'net': get_net_stat, 'io': get_io_stat, } for metric in metrics: try: data.update({metric: getters[metric](hsp, api_type, timeout=timeout)}) except (urllib2.URLError, urllib2.HTTPError, socket.timeout): raise except: msg = "Endpoint: %s, metric '%s' failed: %s" % (endpoint, metric, helper.exc_info()) LOG.warning(msg) continue return data
def _get_statuses(self, servers): async_results = {} for server in servers: if 'scalarizr.key' not in server: msg = "Server: {0}, reason: Missing scalarizr key".format( server['server_id']) LOG.warning(msg) continue if 'scalarizr.updc_port' not in server: api_port = self.scalr_config['scalarizr_update'].get( 'api_port', 8008) server['scalarizr.updc_port'] = api_port self._pool.wait() async_results[server['server_id']] = self._pool.apply_async( self._get_status, (server, )) gevent.sleep(0) # force switch statuses = {} timeout = self.config['instances_connection_timeout'] for server in servers: try: server_id = server['server_id'] statuses[server_id] = async_results[server_id].get( timeout=timeout) except: msg = 'Unable to get update client status, server: {0}, reason: {1}' msg = msg.format(server['server_id'], helper.exc_info()) LOG.warning(msg) return statuses
def ver_from_rpm_repo(self, repo, branch=None): out = {} rpm_repo_url_template = repo['rpm_repo_url'] if rpm_repo_url_template: rpm_repo_url_template = rpm_repo_url_template.strip() if branch: rpm_repo_url_template = rpm_repo_url_template % branch for release in ['5', '6']: rpm_repo_url = rpm_repo_url_template.replace('$releasever', release) rpm_repo_url = rpm_repo_url.replace('$basearch', 'x86_64') url = os.path.join(rpm_repo_url, 'repodata/primary.xml.gz') try: r = requests.get(url) r.raise_for_status() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = 'RPM repository {0} failed, file: {1} not found'.format(repo['rpm_repo_url'], url) LOG.warning(msg) return out s = StringIO.StringIO(r.content) f = gzip.GzipFile(fileobj=s, mode='r') f.seek(0) xml = minidom.parse(f) try: out[rpm_repo_url_template] = self.rpm_pattern_1.findall(xml.toxml())[0].strip() except: out[rpm_repo_url_template] = self.rpm_pattern_2.findall(xml.toxml())[0].strip() return out
def download_aws_billing_file(self, cred, bucket_name, date=None): if date is None: date = datetime.datetime.utcnow().date() conn = get_s3_conn(cred) bucket = conn.get_bucket(bucket_name) account_id = cryptotool.decrypt_scalr(app.crypto_key, cred['account_id']) file_name = get_aws_csv_file_name(account_id, date) key = bucket.get_key(file_name) if not key: msg = "AWS detailed billing CSV file {0} wasn't found in bucket {1}" msg = msg.format(file_name, bucket_name) if datetime.datetime.utcnow().day == 1: LOG.warning(msg) return None else: raise Exception(msg) last_modified_dt = datetime.datetime.strptime(key.last_modified, self.last_modified_format) update_interval = self.config['interval'] utcnow = datetime.datetime.utcnow() delta = datetime.timedelta(seconds=update_interval) condition1 = utcnow > last_modified_dt and utcnow < last_modified_dt + delta condition2 = ((utcnow - last_modified_dt).seconds / 3600) % 8 == 0 if condition1 or condition2: local_file_path = os.path.join(self.tmp_dir, file_name) LOG.debug('Downloading {0}'.format(file_name)) key.get_contents_to_filename(local_file_path) return local_file_path else: return None
def ver_from_rpm_repo(self, repo, branch=None): out = {} rpm_repo_url_template = repo["rpm_repo_url"] if rpm_repo_url_template: rpm_repo_url_template = rpm_repo_url_template.strip() if branch: rpm_repo_url_template = rpm_repo_url_template % branch for release in ["5", "6", "7"]: rpm_repo_url = rpm_repo_url_template.replace("$releasever", release) rpm_repo_url = rpm_repo_url.replace("$basearch", "x86_64") url = os.path.join(rpm_repo_url, "repodata/primary.xml.gz") try: r = requests.get(url) r.raise_for_status() assert r.text, "Empty primary.xml file" s = StringIO.StringIO(r.content) f = gzip.GzipFile(fileobj=s, mode="r") f.seek(0) xml = minidom.parse(f) try: out[rpm_repo_url_template] = self.rpm_pattern_1.findall(xml.toxml())[0].strip() except: out[rpm_repo_url_template] = self.rpm_pattern_2.findall(xml.toxml())[0].strip() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = "RPM repository {0} failed, file not found: {1}" msg = msg.format(repo["rpm_repo_url"], url) LOG.warning(msg) return out
def do_iteration(self): messages = self.get_messages() if not messages: raise exceptions.NothingToDoError() servers = self.get_servers(messages) servers_map = dict((server['server_id'], server) for server in servers) for message in messages: try: if message['server_id'] not in servers_map: msg = ( "Server '{server_id}' doesn't exist or not in right status, set message " "status to 3" ).format(server_id=message['server_id']) LOG.warning(msg) message['status'] = 3 self._pool.wait() self._pool.apply_async(self.update, (message,)) else: server = servers_map[message['server_id']] self._pool.wait() self._pool.apply_async(self.process_message, (message, server)) except: msg = "Unable to process message: {message_id}, reason: {error}" msg = msg.format(message_id=message['messageid'], error=helper.exc_info()) LOG.warning(msg) self._pool.join()
def _handle_webhook_exception(self, webhook): exc = sys.exc_info()[1] if isinstance(exc, ( requests.exceptions.Timeout, requests.exceptions.ProxyError, requests.exceptions.ConnectionError)): if webhook['handle_attempts'] < webhook['attempts']: webhook['status'] = 0 else: webhook['status'] = 2 webhook['error_msg'] = str(sys.exc_info()[0].__name__) msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg) elif isinstance(exc, ( requests.exceptions.RequestException, requests.packages.urllib3.exceptions.HTTPError, requests.packages.urllib3.exceptions.HTTPWarning)): webhook['status'] = 2 webhook['error_msg'] = str(sys.exc_info()[0].__name__) msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg) else: webhook['status'] = 2 webhook['error_msg'] = 'Internal error' msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.error(msg)
def get_net_stat(hsp, api_type='linux', timeout=5): net = hsp.sysinfo.net_stats(timeout=timeout) if api_type == 'linux': ret = { 'in': float(net['eth0']['receive']['bytes']), 'out': float(net['eth0']['transmit']['bytes']), } elif api_type == 'windows': for key in net: if re.match(r'^.*Ethernet Adapter.*$', key) \ or re.match(r'^.*AWS PV Network Device.*$', key): ret = { 'in': float(net[key]['receive']['bytes']), 'out': float(net[key]['transmit']['bytes']), } break else: msg = ( "Can't find ['^.* Ethernet Adapter.*$', '^.*AWS PV Network Device.*$'] " "pattern in api response for endpoint: {0}, available: {1}, use {2}" ).format(hsp.endpoint, net.keys(), net.keys()[0]) LOG.warning(msg) first_key = net.keys()[0] ret = { 'in': float(net[first_key]['receive']['bytes']), 'out': float(net[first_key]['transmit']['bytes']), } else: raise APIError("Unsupported API type '%s' for NET stat" % api_type) return ret
def do_iteration(self): messages = self.get_messages() if not messages: raise exceptions.NothingToDoError() servers = self.get_servers(messages) servers_map = dict((server['server_id'], server) for server in servers) for message in messages: try: if message['server_id'] not in servers_map: msg = ( "Server '{server_id}' doesn't exist or not in right status, set message " "status to 3").format(server_id=message['server_id']) LOG.warning(msg) message['status'] = 3 self._pool.wait() self._pool.apply_async(self.update, (message, )) else: server = servers_map[message['server_id']] self._pool.wait() self._pool.apply_async(self.process_message, (message, server)) except: msg = "Unable to process message: {message_id}, reason: {error}" msg = msg.format(message_id=message['messageid'], error=helper.exc_info()) LOG.warning(msg) self._pool.join()
def _plot(self, kwds, tz, metric): img_dir = self._get_image_dir(kwds) url_dir = self._get_url_dir(kwds) rrd_files = self._get_rrd_files(kwds, metric) if not rrd_files: msg = "Coudn't find rrd file(s) for request: {0}, metric: {1}" msg = msg.format(kwds, metric) LOG.warning(msg) raise Plotter.IOError('Statistics are not available') if metric == 'io': url = dict() options = rrd.GRAPH_OPT[kwds['period']] for rrd_file in rrd_files: dev = os.path.basename(rrd_file)[:-4] url[dev] = dict() img_file = os.path.join( img_dir, 'io_bits_%s_%s.png' % (dev, kwds['period'])) url[dev]['bits_per_sec'] = os.path.join( url_dir, 'io_bits_%s_%s.png' % (dev, kwds['period'])) rrd.plot_io_bits(str(img_file), str(rrd_file), options, tz=tz) img_file = os.path.join( img_dir, 'io_ops_%s_%s.png' % (dev, kwds['period'])) url[dev]['operations_per_sec'] = os.path.join( url_dir, 'io_ops_%s_%s.png' % (dev, kwds['period'])) rrd.plot_io_ops(str(img_file), str(rrd_file), options, tz=tz) else: rrd_file = rrd_files[0] img_file = os.path.join(img_dir, '%s_%s.png' % (metric, kwds['period'])) if not os.path.exists( img_file) or os.path.getmtime(img_file) + 60 < time.time(): options = rrd.GRAPH_OPT[kwds['period']] self._plotters[metric](str(img_file), str(rrd_file), options) url = os.path.join(url_dir, '%s_%s.png' % (metric, kwds['period'])) return url
def get_metrics(host, port, key, api_type, metrics, headers=None, timeout=5): assert host, 'host' assert port, 'port' assert key, 'key' assert api_type, 'api_type' assert metrics, 'metrics' data = dict() endpoint = 'http://%s:%s' % (host, port) security = rpc.Security(key) hsp = rpc.HttpServiceProxy(endpoint, security=security, headers=headers) getters = { 'cpu': get_cpu_stat, 'la': get_la_stat, 'mem': get_mem_info, 'net': get_net_stat, 'io': get_io_stat, } for metric in metrics: try: data.update({metric: getters[metric](hsp, api_type, timeout=timeout)}) except (urllib2.URLError, urllib2.HTTPError, socket.timeout): msg = "Endpoint: {endpoint}, headers: {headers}, metric: '{metric}', reason: {err}" msg = msg.format( endpoint=endpoint, headers=headers, metric=metric, err=helper.exc_info()) raise Exception(msg) except: msg = "Endpoint: {endpoint}, headers: {headers}, metric '{metric}' failed, reason: {er}" msg = msg.format( endpoint=endpoint, headers=headers, metric=metric, err=helper.exc_info()) LOG.warning(msg) continue return data
def _get_statuses(self, servers): async_results = {} for server in servers: if 'scalarizr.key' not in server: msg = "Server: {0}, reason: Missing scalarizr key".format(server['server_id']) LOG.warning(msg) continue if 'scalarizr.updc_port' not in server: api_port = self.scalr_config['scalarizr_update'].get('api_port', 8008) server['scalarizr.updc_port'] = api_port self._pool.wait() async_results[server['server_id']] = self._pool.apply_async(self._get_status, (server,)) gevent.sleep(0) # force switch statuses = {} timeout = self.config['instances_connection_timeout'] for server in servers: try: server_id = server['server_id'] statuses[server_id] = async_results[server_id].get(timeout=timeout) except: msg = 'Unable to get update client status, server: {0}, reason: {1}' msg = msg.format(server['server_id'], helper.exc_info()) LOG.warning(msg) return statuses
def __init__(self, record=None): Table.__init__(self) self._types = { 'usage_id': UUIDType, 'dtime': QuoteType, 'platform': QuoteType, 'url': QuoteType, 'cloud_location': QuoteType, 'instance_type': QuoteType, 'os': NoQuoteType, 'num': NoQuoteType, 'cost': NoQuoteType, } self._fill(record) if 'usage_id' not in self: try: formatted = self._format() unique = '; '.join([ str(formatted['dtime']).strip(), str(formatted['platform']).strip(), str(formatted['url']).strip(), str(formatted['cloud_location']).strip(), str(formatted['instance_type']).strip(), str(formatted['os']).strip(), ]) self['usage_id'] = uuid.uuid5(UUID, unique).hex except KeyError: msg = "Can't set not managed usage_id for record: {record}, reason: {error}" msg = msg.format(record=record, error=helper.exc_info()) LOG.warning(msg)
def gce(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() project_id = cryptotool.decrypt_scalr(app.crypto_key, cred['project_id']) key = _gce_key(cred) conn, http = _gce_conn(cred, key=key) request = conn.zones().list(project=project_id) resp = request.execute(http=http) zones = [_['name'] for _ in resp['items']] if 'items' in resp else [] app.pool.wait() async_results = dict( (zone, app.pool.apply_async(_gce_zone, args=(zone, key, cred,))) for zone in zones ) gevent.sleep(0) # force switch for zone, async_result in async_results.iteritems(): try: zone_nodes = async_result.get(timeout=app.config['cloud_connection_timeout'] + 1) if zone_nodes: result.append(zone_nodes) except gevent.timeout.Timeout: async_result.kill() msg = 'platform: {platform}, zone: {zone}, env_id: {env_id}, reason: timeout' msg = msg.format(platform=cred.platform, zone=zone, env_id=cred.env_id) LOG.warning(msg) return result
def do_iteration(self): while len(self._processing_messages) > self.max_processing_messages: time.sleep(1) messages = self.get_messages() if not messages: time.sleep(self.nothing_todo_sleep) return servers = self.get_servers(messages) servers_map = dict((server['server_id'], server) for server in servers) for message in messages: try: if message['messageid'] in self._processing_messages: continue self._processing_messages.add(message['messageid']) if message['server_id'] not in servers_map: msg = ( "Server '{server_id}' doesn't exist or not in right status, set message " "status to 3").format(server_id=message['server_id']) LOG.warning(msg) message['status'] = 3 self._pool.wait() self._pool.apply_async(self.update, (message, )) else: server = servers_map[message['server_id']] self._pool.wait() self._pool.apply_async(self.process_message, (message, server)) except: msg = "Unable to process message: {message_id}, reason: {error}" msg = msg.format(message_id=message['messageid'], error=helper.exc_info()) LOG.warning(msg)
def download_aws_billing_file(self, cred, bucket_name, date=None): if date is None: date = datetime.datetime.utcnow().date() conn = get_s3_conn(cred) bucket = conn.get_bucket(bucket_name) account_id = cryptotool.decrypt_scalr(app.crypto_key, cred['account_id']) file_name = get_aws_csv_file_name(account_id, date) key = bucket.get_key(file_name) if not key: msg = "AWS detailed billing CSV file {0} wasn't found in bucket {1}" msg = msg.format(file_name, bucket_name) if datetime.datetime.utcnow().day == 1: LOG.warning(msg) return None else: raise Exception(msg) last_modified_dt = datetime.datetime.strptime( key.last_modified, self.last_modified_format) update_interval = self.config['interval'] utcnow = datetime.datetime.utcnow() delta = datetime.timedelta(seconds=update_interval) condition1 = utcnow > last_modified_dt and utcnow < last_modified_dt + delta condition2 = ((utcnow - last_modified_dt).seconds / 3600) % 8 == 0 if condition1 or condition2: local_file_path = os.path.join(self.tmp_dir, file_name) LOG.debug('Downloading {0}'.format(file_name)) key.get_contents_to_filename(local_file_path) return local_file_path else: return None
def do_iteration(self): while len(self._processing_messages) > self.max_processing_messages: time.sleep(1) messages = self.get_messages() if not messages: time.sleep(self.nothing_todo_sleep) return servers = self.get_servers(messages) servers_map = dict((server['server_id'], server) for server in servers) for message in messages: try: if message['messageid'] in self._processing_messages: continue self._processing_messages.add(message['messageid']) if message['server_id'] not in servers_map: msg = ( "Server '{server_id}' doesn't exist or not in right status, set message " "status to 3" ).format(server_id=message['server_id']) LOG.warning(msg) message['status'] = 3 self._pool.wait() self._pool.apply_async(self.update, (message,)) else: server = servers_map[message['server_id']] self._pool.wait() self._pool.apply_async(self.process_message, (message, server)) except: msg = "Unable to process message: {message_id}, reason: {error}" msg = msg.format(message_id=message['messageid'], error=helper.exc_info()) LOG.warning(msg)
def sorted_data_update(sorted_data): for region_data in sorted_data: for server in region_data['managed']: if server.get('os', None) is not None: continue query = ( "SELECT os_type os " "FROM servers " "WHERE server_id='{server_id}'" ).format(server_id=server['server_id']) result = app.scalr_db.execute(query, retries=1) if not result: query = ( "SELECT value AS os " "FROM server_properties " "WHERE server_id='{server_id}' " "AND name='os_type'" ).format(server_id=server['server_id']) result = app.scalr_db.execute(query, retries=1) if not result: server['os'] = 'linux' msg = "Can't detect OS type for server: {0}, set 'linux'".format( server['server_id']) LOG.warning(msg) else: server['os'] = result[0]['os'] for server in region_data['managed']: server['os'] = analytics.os_map[server.get('os', None)] for server in region_data['not_managed']: server['os'] = analytics.os_map[server.get('os', None)]
def _handle_webhook_exception(self, webhook): exc = sys.exc_info()[1] if isinstance( exc, (requests.exceptions.Timeout, requests.exceptions.ProxyError, requests.exceptions.ConnectionError)): if webhook['handle_attempts'] < webhook['attempts']: webhook['status'] = 0 else: webhook['status'] = 2 webhook['error_msg'] = str(sys.exc_info()[0].__name__) msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg) elif isinstance(exc, (requests.exceptions.RequestException, requests.packages.urllib3.exceptions.HTTPError, requests.packages.urllib3.exceptions.HTTPWarning)): webhook['status'] = 2 webhook['error_msg'] = str(sys.exc_info()[0].__name__) msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg) else: webhook['status'] = 2 webhook['error_msg'] = 'Internal error' msg = "Unable to process webhook: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.error(msg)
def sorted_data_update(sorted_data): for region_data in sorted_data: for server in region_data['managed']: if server.get('os', None) is not None: continue query = ("SELECT os_type os " "FROM servers " "WHERE server_id='{server_id}'").format( server_id=server['server_id']) result = app.scalr_db.execute(query, retries=1) if not result: query = ("SELECT value AS os " "FROM server_properties " "WHERE server_id='{server_id}' " "AND name='os_type'").format( server_id=server['server_id']) result = app.scalr_db.execute(query, retries=1) if not result: server['os'] = 'linux' msg = "Can't detect OS type for server: {0}, set 'linux'".format( server['server_id']) LOG.warning(msg) else: server['os'] = result[0]['os'] for server in region_data['managed']: server['os'] = analytics.os_map[server.get('os', None)] for server in region_data['not_managed']: server['os'] = analytics.os_map[server.get('os', None)]
def get_prices(self, servers): """ :returns: dict {account_id: {platform_url: {cloud_location: {instance_type: {os: cost}}}}} """ prices = dict() for raw_prices in self._get_raw_prices(servers): for raw_price in raw_prices: try: account_id = raw_price['account_id'] platform = raw_price['platform'] url = raw_price['url'] platform_url = '%s;%s' % (platform, url) cloud_location = raw_price['cloud_location'] instance_type = raw_price['instance_type'] os_type = raw_price['os'] cost = raw_price['cost'] prices.setdefault(account_id, dict()) prices[account_id].setdefault(platform_url, dict()) prices[account_id][platform_url].setdefault( cloud_location, dict()) prices[account_id][platform_url][ cloud_location].setdefault(instance_type, dict()) prices[account_id][platform_url][cloud_location][ instance_type][os_type] = cost except KeyError: msg = "Unable to get price from raw price, reason: {error}" msg = msg.format(error=helper.exc_info()) LOG.warning(msg) return prices
def delete_file(file_path): msg = "Deleting file: %s" % file_path LOG.debug(msg) if os.path.exists(file_path): try: os.remove(file_path) except: LOG.warning(exc_info())
def ec2(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() if cred['account_type'] == 'regular': regions = [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1', ] elif cred['account_type'] == 'gov-cloud': regions = [ 'us-gov-west-1', ] elif cred['account_type'] == 'cn-cloud': regions = [ 'cn-north-1', ] else: msg = 'Unsupported account type for ec2 platform: {0}'.format( cred['account_type']) raise Exception(msg) app.pool.wait() async_results = dict( (region, app.pool.apply_async(_ec2_region, args=( region, cred, ))) for region in regions) gevent.sleep(0) # force switch timeout = app.config['cloud_connection_timeout'] for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=timeout) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = 'platform: {platform}, region: {region}, env_id: {env_id}, reason: timeout' msg = msg.format(platform=cred.platform, region=region, env_id=cred.env_id) LOG.warning(msg) return result
def do_iteration(self): self.clear_cache() servers_for_update = self.get_servers_for_update() for server in servers_for_update: try: self._pool.wait() self._pool.apply_async(self.update_server, (server, )) gevent.sleep(0) # force switch except: LOG.warning(helper.exc_info()) self._pool.join()
def _openstack(provider, cred): result = list() username, password, auth_version, keystone_url, tenant_name = _openstack_cred( cred) url = urlparse.urlparse(keystone_url) cls = get_driver(provider) driver = cls( username, password, ex_force_auth_url=url.geturl(), ex_force_base_url='%s://%s' % (url.scheme, url.netloc), ex_tenant_name=tenant_name, ex_force_auth_version=auth_version, ) proxy_url = app.proxy_settings.get(cred.platform, {}).get('url') driver.connection.set_http_proxy(proxy_url=proxy_url) service_catalog = _libcloud_get_service_catalog(driver) service_names = service_catalog.get_service_names(service_type='compute') regions = service_catalog.get_regions(service_type='compute') for service_name in service_names: app.pool.wait() async_results = dict( (region, app.pool.apply_async(_openstack_region, args=(provider, service_name, region, cred))) for region in regions) gevent.sleep(0) # force switch for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get( timeout=app.config['cloud_connection_timeout'] + 1) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = ( "platform: '{platform}', envs_ids: {envs_ids}, url: '{url}', " "tenant_name: '{tenant_name}', service_name='{service_name}', " "region: '{region}', auth_version: {auth_version}. Reason: timeout" ) msg = msg.format(platform=cred.platform, envs_ids=cred.envs_ids, url=url, tenant_name=tenant_name, service_name=service_name, region=region, auth_version=auth_version) LOG.warning(msg) return result
def _handle_exception(e, msg): if type(e) == boto.exception.EC2ResponseError and e.status in [401, 403]: LOG.warning(msg) elif type(e) in [ libcloud.common.types.InvalidCredsError, libcloud.common.types.LibcloudError, libcloud.common.types.MalformedResponseError, gevent.timeout.Timeout, socket.timeout, socket.gaierror ]: LOG.warning(msg) else: LOG.error(msg)
def _openstack(provider, cred): result = list() username, password, auth_version, keystone_url, tenant_name = _openstack_cred(cred) url = urlparse.urlparse(keystone_url) cls = get_driver(provider) driver = cls( username, password, ex_force_auth_url=url.geturl(), ex_force_base_url="%s://%s" % (url.scheme, url.netloc), ex_tenant_name=tenant_name, ex_force_auth_version=auth_version, ) proxy_url = app.proxy_settings.get(cred.platform, {}).get("url") driver.connection.set_http_proxy(proxy_url=proxy_url) service_catalog = _libcloud_get_service_catalog(driver) service_names = service_catalog.get_service_names(service_type="compute") regions = service_catalog.get_regions(service_type="compute") for service_name in service_names: app.pool.wait() async_results = dict( (region, app.pool.apply_async(_openstack_region, args=(provider, service_name, region, cred))) for region in regions ) gevent.sleep(0) # force switch for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=app.config["cloud_connection_timeout"] + 1) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = ( "platform: '{platform}', envs_ids: {envs_ids}, url: '{url}', " "tenant_name: '{tenant_name}', service_name='{service_name}', " "region: '{region}', auth_version: {auth_version}. Reason: timeout" ) msg = msg.format( platform=cred.platform, envs_ids=cred.envs_ids, url=url, tenant_name=tenant_name, service_name=service_name, region=region, auth_version=auth_version, ) LOG.warning(msg) return result
def _process_server(self, server): data = dict() try: data = self._get_metrics_api(server) except: msg = "Server: '%s' API failed: %s" % (server['server_id'], helper.exc_info()) LOG.warning(msg) result = { 'farm_id': server['farm_id'], 'farm_role_id': server['farm_role_id'], 'index': server['index'], 'data': data, } return result
def ec2(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() if cred['account_type'] == 'regular': regions = [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1', ] elif cred['account_type'] == 'gov-cloud': regions = [ 'us-gov-west-1', ] elif cred['account_type'] == 'cn-cloud': regions = [ 'cn-north-1', ] else: msg = 'Unsupported account type for ec2 platform: {0}'.format(cred['account_type']) raise Exception(msg) app.pool.wait() async_results = dict( (region, app.pool.apply_async(_ec2_region, args=(region, cred,))) for region in regions ) gevent.sleep(0) # force switch timeout = app.config['cloud_connection_timeout'] for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=timeout) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = 'platform: {platform}, region: {region}, env_id: {env_id}, reason: timeout' msg = msg.format(platform=cred.platform, region=region, env_id=cred.env_id) LOG.warning(msg) return result
def _process_server(self, server): data = dict() try: data = self._get_metrics_api(server) except: msg = "Server: '%s' API failed: %s" % (server['server_id'], helper.exc_info()) LOG.warning(msg) result = { 'farm_id': server['farm_id'], 'farm_roleid': server['farm_roleid'], 'index': server['index'], 'data': data, } return result
def _openstack(provider, cred): result = list() username, password, auth_version, keystone_url, tenant_name = _openstack_cred(cred) url = urlparse.urlparse(keystone_url) cls = get_driver(provider) driver = cls( username, password, ex_force_auth_url=url.geturl(), ex_force_base_url='%s://%s' % (url.scheme, url.netloc), ex_tenant_name=tenant_name, ex_force_auth_version=auth_version, ) driver.connection.set_http_proxy(proxy_url=app.proxy_url[cred.platform]) service_catalog = _libcloud_get_service_catalog(driver) service_names = service_catalog.get_service_names(service_type='compute') regions = service_catalog.get_regions(service_type='compute') for service_name in service_names: app.pool.wait() async_results = dict( ( region, app.pool.apply_async( _openstack_region, args=(provider, service_name, region, cred) ) ) for region in regions ) gevent.sleep(0) # force switch for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=app.config['cloud_connection_timeout'] + 1) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = ( 'platform: {platform}, env_id: {env_id}, url: {url}, ' 'tenant_name: {tenant_name}, service_name={service_name}, ' 'region: {region}, auth_version: {auth_version}, reason: timeout') msg = msg.format( platform=cred.platform, env_id=cred.env_id, url=url, tenant_name=tenant_name, service_name=service_name, region=region, auth_version=auth_version) LOG.warning(msg) return result
def ec2(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() regions = { 'regular': [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'ap-northeast-2', 'sa-east-1', ], 'gov-cloud': ['us-gov-west-1'], 'cn-cloud': ['cn-north-1'], }.get(cred.get('account_type')) if not regions: msg = "Unsupported account type for 'ec2' platform: '{}'".format( cred.get('account_type')) raise Exception(msg) app.pool.wait() async_results = dict( (region, app.pool.apply_async(_ec2_region, args=( region, cred, ))) for region in regions) gevent.sleep(0) # force switch timeout = app.config['cloud_connection_timeout'] for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=timeout) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = "platform: '{platform}', region: '{region}', envs_ids: {envs_ids}. Reason: timeout" msg = msg.format(platform=cred.platform, region=region, envs_ids=cred.envs_ids) LOG.warning(msg) return result
def update_server(self, server): try: szr_upd_client = self._get_szr_upd_client(server) timeout = self.config["instances_connection_timeout"] msg = "Trying to update server: {0}, version: {1}".format(server["server_id"], server["scalarizr.version"]) LOG.debug(msg) try: result_id = szr_upd_client.update(async=True, timeout=timeout) except: msg = "Unable to update, reason: {0}".format(helper.exc_info()) raise Exception(msg) LOG.debug("Server: {0}, result: {1}".format(server["server_id"], result_id)) except: msg = "Server failed: {0}, reason: {1}".format(server["server_id"], helper.exc_info()) LOG.warning(msg)
def do_iteration(self): servers = self.get_servers_for_update() for server in servers: try: self._pool.wait() self._pool.apply_async(self.update_server, (server,)) gevent.sleep(0) # force switch except: LOG.warning(helper.exc_info()) self._pool.join() try: self.update_scalr_repo_data() except: msg = "Unable to update scalr.settings table, reason: {0}".format(helper.exc_info()) LOG.error(msg)
def _get_servers_scheduled_for_update(self, servers): servers_scheduled_for_update = [] for server in servers: try: version = server['scalarizr.version'] if not version or parse_version(version) < parse_version('2.7.7'): continue if not schedule_parser.Schedule(server['schedule']).intime(): continue servers_scheduled_for_update.append(server) except: msg = "Server: {0}, reason: {1}".format(server['server_id'], helper.exc_info()) LOG.warning(msg) continue return servers_scheduled_for_update
def do_iteration(self): servers = self.get_servers_for_update() for server in servers: try: self._pool.wait() self._pool.apply_async(self.update_server, (server, )) gevent.sleep(0) # force switch except: LOG.warning(helper.exc_info()) self._pool.join() try: self.update_scalr_repo_data() except: msg = 'Unable to update scalr.settings table, reason: {0}'.format( helper.exc_info()) LOG.error(msg)
def update_server(self, server): try: szr_upd_client = self._get_szr_upd_client(server) timeout = self.config['instances_connection_timeout'] msg = "Trying to update server: {0}, version: {1}".format( server['server_id'], server['scalarizr.version']) LOG.debug(msg) try: result_id = szr_upd_client.update(async=True, timeout=timeout) except: msg = 'Unable to update, reason: {0}'.format(helper.exc_info()) raise Exception(msg) LOG.debug("Server: {0}, result: {1}".format(server['server_id'], result_id)) except: msg = "Server failed: {0}, reason: {1}".format(server['server_id'], helper.exc_info()) LOG.warning(msg)
def ver_from_deb_repo(self, repo, branch=None): out = {} deb_repo_url_template = repo['deb_repo_url'] if deb_repo_url_template: deb_repo_url_template = deb_repo_url_template.strip() if branch: deb_repo_url_template = deb_repo_url_template % branch deb_repo_url = '/'.join(deb_repo_url_template.split()) url = os.path.join(deb_repo_url, 'Packages') try: r = requests.get(url) r.raise_for_status() out[deb_repo_url_template] = self.deb_pattern.findall(r.text)[0].strip() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = 'Deb repository {0} failed, file: {1} not found'.format(repo['deb_repo_url'], url) LOG.warning(msg) return out
def filter_creds(self, creds): tmp = dict() for cred in creds: try: unique = cred.unique if unique not in tmp: tmp[unique] = { 'env_id': [cred.env_id], 'cred': cred, } else: tmp[unique]['env_id'].append(cred.env_id) except: msg = 'Unable to filter credentials, env_id: {0}, platform: {1}, reason: {2}' msg = msg.format(cred.env_id, cred.platform, helper.exc_info()) LOG.warning(msg) return tmp.values()
def _set_next_update_dt(self, servers): for server in servers: next_update_dt = str(self._scheduled_on(server['schedule'])) if next_update_dt != server['scheduled_on']: query = ("""INSERT INTO farm_role_settings """ """(farm_roleid, name, value) """ """VALUES ({0}, 'scheduled_on', '{1}') """ """ON DUPLICATE KEY UPDATE value='{1}'""").format( server['farm_roleid'], next_update_dt) msg = "Set next update datetime for server: {0} to: {1}" msg = msg.format(server['server_id'], next_update_dt) LOG.debug(msg) try: self._db.execute(query, retries=1) except: msg = 'Unable to update next update datetime for server: {0}, reason: {1}' msg = msg.format(server['server_id'], helper.exc_info()) LOG.warning(msg)
def _check_request(self, kwds): try: assert 'hash' in kwds, "Missing required parameter 'hash'" assert 'farmId' in kwds, "Missing required parameter 'farmId'" int(kwds['farmId']) assert 'metrics' in kwds, "Missing required parameter 'metrics'" assert 'period' in kwds, "Missing required parameter 'period'" if 'index' in kwds: assert 'farmRoleId' in kwds, "Missing required parameter 'farmRoleId'" int(kwds['farmRoleId']) int(kwds['index']) elif 'farmRoleId' in kwds: int(kwds['farmRoleId']) assert kwds['period'] in ['daily', 'weekly', 'monthly', 'yearly'], \ "Unsupported period '%s'" % kwds['period'] except (AssertionError, ValueError): LOG.warning(helper.exc_info()) raise Plotter.BadRequestError('Bad request')
def cloudstack(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() app.pool.wait() async_result = app.pool.apply_async(_cloudstack, args=(cred,)) gevent.sleep(0) # force switch try: result = async_result.get(timeout=app.config["cloud_connection_timeout"]) except gevent.timeout.Timeout: async_result.kill() msg = "platform: '{platform}', envs_ids: {envs_ids}. Reason: timeout" msg = msg.format(platform=cred.platform, envs_ids=cred.envs_ids) LOG.warning(msg) return result
def ec2(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() regions = { 'regular': [ 'us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', 'sa-east-1', ], 'gov-cloud': ['us-gov-west-1'], 'cn-cloud': ['cn-north-1'], }.get(cred.get('account_type')) if not regions: msg = "Unsupported account type for 'ec2' platform: '{}'".format(cred.get('account_type')) raise Exception(msg) app.pool.wait() async_results = dict( (region, app.pool.apply_async(_ec2_region, args=(region, cred,))) for region in regions ) gevent.sleep(0) # force switch timeout = app.config['cloud_connection_timeout'] for region, async_result in async_results.iteritems(): try: region_nodes = async_result.get(timeout=timeout) if region_nodes: result.append(region_nodes) except gevent.timeout.Timeout: async_result.kill() msg = "platform: '{platform}', region: '{region}', envs_ids: {envs_ids}. Reason: timeout" msg = msg.format(platform=cred.platform, region=region, envs_ids=cred.envs_ids) LOG.warning(msg) return result
def process_message(self, message, server): try: try: request = self.make_request(message, server) except: message['status'] = 3 msg = "Make request failed, reason: {error}".format( error=helper.exc_info()) raise Exception(msg) if not request['url']: message['status'] = 3 msg = "Wrong request: {request}".format(request=request) raise Exception(msg) msg = "Send message: {message_id}, request: {request}" msg = msg.format(message_id=message['messageid'], request={ 'url': request['url'], 'headers': request['headers'] }) LOG.debug(msg) r = requests.post( request['url'], data=request['data'], headers=request['headers'], timeout=self.config['instances_connection_timeout']) if r.status_code != 201: msg = "Bad response code: {code}".format(code=r.status_code) raise Exception(msg) message['status'] = 1 msg = "Delivery Ok, message: {message_id}" msg = msg.format(message_id=message['messageid']) LOG.debug(msg) except: if message['status'] == 0 and int(message['handle_attempts']) >= 2: message['status'] = 3 msg = "Delivery failed, message: {message_id}, server: {server}, reason: {error}" server['scalarizr.key'] = '******' msg = msg.format(message_id=message['messageid'], server=server, error=helper.exc_info()) LOG.warning(msg) self.update(message)
def clean(self): for directory in os.listdir(self.config['rrd_dir']): for farm_id in os.listdir('%s/%s' % (self.config['rrd_dir'], directory)): try: if self._is_farm_exists({'id': int(farm_id)}): continue dir_to_delete = os.path.join(self.config['rrd_dir'], directory, farm_id) LOG.debug('Delete farm {0}: {1}'.format(farm_id, dir_to_delete)) if self.args['--test']: continue shutil.rmtree(dir_to_delete, ignore_errors=True) except KeyboardInterrupt: raise except pymysql.err.Error as e: if e.args[0] == KeyboardInterrupt: raise KeyboardInterrupt LOG.warning(helper.exc_info()) except: LOG.warning(helper.exc_info())
def cloudstack(cred): """ :returns: list [{'region': str, 'timestamp': int, 'nodes': list}] """ result = list() app.pool.wait() async_result = app.pool.apply_async(_cloudstack, args=(cred, )) gevent.sleep(0) # force switch try: result = async_result.get( timeout=app.config['cloud_connection_timeout']) except gevent.timeout.Timeout: async_result.kill() msg = 'platform: {platform}, env_id: {env_id}. Reason: timeout' msg = msg.format(platform=cred.platform, env_id=cred.env_id) LOG.warning(msg) return result
def _set_next_update_dt(self, servers): for server in servers: next_update_dt = str(self._scheduled_on(server['schedule'])) if next_update_dt != server['scheduled_on']: query = ( """INSERT INTO farm_role_settings """ """(farm_roleid, name, value) """ """VALUES ({0}, 'scheduled_on', '{1}') """ """ON DUPLICATE KEY UPDATE value='{1}'""" ).format(server['farm_roleid'], next_update_dt) msg = "Set next update datetime for server: {0} to: {1}" msg = msg.format(server['server_id'], next_update_dt) LOG.debug(msg) try: self._db.execute(query, retries=1) except: msg = 'Unable to update next update datetime for server: {0}, reason: {1}' msg = msg.format(server['server_id'], helper.exc_info()) LOG.warning(msg)
def ver_from_deb_repo(self, repo, branch=None): out = {} deb_repo_url_template = repo["deb_repo_url"] if deb_repo_url_template: deb_repo_url_template = deb_repo_url_template.strip() if branch: deb_repo_url_template = deb_repo_url_template % branch deb_repo_url = "/".join(deb_repo_url_template.split()) url = os.path.join(deb_repo_url, "Packages") try: r = requests.get(url) r.raise_for_status() assert r.text, "Empty Packages file" out[deb_repo_url_template] = self.deb_pattern.findall(r.text)[0].strip() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = "Deb repository {0} failed, file not found: {1}" msg = msg.format(repo["deb_repo_url"], url) LOG.warning(msg) return out
def get_servers_for_update(self): servers_for_update_high_pri = [] servers_for_update_low_pri = [] for servers in self._get_db_servers(): self._load_servers_data(servers) self._set_next_update_dt(servers) servers_scheduled_for_update = self._get_servers_scheduled_for_update( servers) self._db.load_vpc_settings(servers_scheduled_for_update) statuses = self._get_statuses(servers_scheduled_for_update) for server in servers_scheduled_for_update: try: if server['server_id'] not in statuses: continue if not self._is_server_for_update( server, statuses[server['server_id']]): continue if server['schedule'] == '* * *': free = self.config['chunk_size'] - len( servers_for_update_high_pri) if len(servers_for_update_low_pri) < free: servers_for_update_low_pri.append(server) else: servers_for_update_high_pri.append(server) if len(servers_for_update_high_pri ) >= self.config['chunk_size']: break except: msg = "Server: {0}, reason: {1}".format( server['server_id'], helper.exc_info()) LOG.warning(msg) else: continue break if len(servers_for_update_high_pri) < self.config['chunk_size']: servers_for_update = servers_for_update_high_pri + servers_for_update_low_pri servers_for_update = servers_for_update[0:self. config['chunk_size']] else: servers_for_update = servers_for_update_high_pri return servers_for_update
def ver_from_win_repo(self, repo, branch=None): out = {} win_repo_url_template = repo['win_repo_url'] if win_repo_url_template: win_repo_url_template = win_repo_url_template.strip() if branch: win_repo_url = win_repo_url_template % branch else: win_repo_url = win_repo_url_template url = os.path.join(win_repo_url, 'x86_64/index') try: r = requests.get(url) r.raise_for_status() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = 'Win repository {0} failed, file: {1} not found'.format(repo['win_repo_url'], url) LOG.warning(msg) return out out[win_repo_url] = self.win_pattern.findall(r.text)[0].split('-')[0] return out
def ver_from_deb_repo(self, repo, branch=None): out = {} deb_repo_url_template = repo['deb_repo_url'] if deb_repo_url_template: deb_repo_url_template = deb_repo_url_template.strip() if branch: deb_repo_url_template = deb_repo_url_template % branch deb_repo_url = '/'.join(deb_repo_url_template.split()) url = os.path.join(deb_repo_url, 'Packages') try: r = requests.get(url) r.raise_for_status() out[deb_repo_url_template] = self.deb_pattern.findall( r.text)[0].strip() except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = 'Deb repository {0} failed, file: {1} not found'.format( repo['deb_repo_url'], url) LOG.warning(msg) return out
def update_event(self, webhook): try: assert webhook['history_id'], 'event_id is null' if webhook['status'] == 1: query = ("""UPDATE events """ """SET wh_completed=wh_completed+1 """ """WHERE events.event_id='{event_id}'""").format( **webhook) elif webhook['status'] == 2: query = ("""UPDATE events """ """SET wh_failed=wh_failed+1 """ """WHERE events.event_id='{event_id}'""").format( **webhook) else: return self._db.execute(query, retries=3) except: msg = "Events update failed, history_id: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg)
def ver_from_win_repo(self, repo, branch=None): out = {} win_repo_url_template = repo["win_repo_url"] if win_repo_url_template: win_repo_url_template = win_repo_url_template.strip() if branch: win_repo_url = win_repo_url_template % branch else: win_repo_url = win_repo_url_template url = os.path.join(win_repo_url, "x86_64/index") try: r = requests.get(url) r.raise_for_status() assert r.text, "Empty index file" out[win_repo_url] = self.win_pattern.findall(r.text)[0].split("-")[0] except (requests.exceptions.HTTPError, requests.exceptions.InvalidSchema): msg = "Win repository {0} failed, file not found: {1}" msg = msg.format(repo["win_repo_url"], url) LOG.warning(msg) return out
def update_webhook(self, webhook): webhook['response_code'] = webhook.get('response_code', 'NULL') webhook['error_msg'] = pymysql.escape_string(webhook['error_msg'])[0:255] while True: try: query = ( """UPDATE webhook_history """ """SET status={status}, response_code={response_code}, """ """error_msg="{error_msg}", handle_attempts={handle_attempts}, """ """dtlasthandleattempt='{dtlasthandleattempt}' """ """WHERE history_id=UNHEX('{history_id}')""" ).format(**webhook) self._db.execute(query) break except KeyboardInterrupt: raise except: msg = "Webhook update failed, history_id: {0}, reason: {1}" msg = msg.format(webhook['history_id'], helper.exc_info()) LOG.warning(msg) time.sleep(5)
def process_message(self, message, server): try: try: request = self.make_request(message, server) except: message['status'] = 3 msg = "Make request failed, reason: {error}".format(error=helper.exc_info()) raise Exception(msg) if not request['url']: message['status'] = 3 msg = "Wrong request: {request}".format(request=request) raise Exception(msg) msg = "Send message: {message_id}, request: {request}" msg = msg.format( message_id=message['messageid'], request={'url': request['url'], 'headers': request['headers']}) LOG.debug(msg) r = requests.post( request['url'], data=request['data'], headers=request['headers'], timeout=self.config['instances_connection_timeout']) if r.status_code != 201: msg = "Bad response code: {code}".format(code=r.status_code) raise Exception(msg) message['status'] = 1 msg = "Delivery Ok, message: {message_id}" msg = msg.format(message_id=message['messageid']) LOG.debug(msg) except: if message['status'] == 0 and int(message['handle_attempts']) >= 2: message['status'] = 3 msg = "Delivery failed, message: {message_id}, server: {server}, reason: {error}" server['scalarizr.key'] = '******' msg = msg.format( message_id=message['messageid'], server=server, error=helper.exc_info()) LOG.warning(msg) self.update(message)