Source code for opslib.icsmeta

"""
IcsMeta: Library for Meta
--------------------------

+---------------------+------------+--+
| This is the IcsMeta common library. |
+---------------------+------------+--+
"""

import os
import re
import json
import time

from boto import config
from boto.utils import get_instance_metadata as get_metadata
from opslib.icss3 import IcsS3
from opslib.icsec2 import IcsEc2
from opslib.icsutils.misc import get_userdata
from opslib.icsutils.misc import is_valid_ip
from opslib.icsutils.icsalert import IcsAlert
from opslib.icsexception import IcsMetaException

import logging
log = logging.getLogger(__name__)


[docs]class IcsMeta(object):
[docs] def __init__(self): """ Initialize Ics Meta (meta-data, user-data, credentials, tags) """ self.meta_data = IcsMeta.get_meta_data() self.user_data = json.loads(IcsMeta.get_user_data()) self.credentials = self.get_credentials() self.tags = self.get_machine_tags()
@staticmethod
[docs] def get_meta_data(timeout=None, url=None, num_retries=None): """ Get instance meta data :type timeout: int :param timeout: timeout for the request :type url: string :param url: metadata_service_url :type num_retries: int :param num_retries: how many times to retry :rtype: dict :return: instance meta data as a dictionary """ if timeout is None: timeout = config.getint('Boto', 'http_socket_timeout', 70) if num_retries is None: num_retries = config.getint('Boto', 'num_retries', 5) if url is None: url = config.get( 'Boto', 'metadata_service_url', 'http://169.254.169.254') return get_metadata(timeout=timeout, url=url, num_retries=num_retries)
@staticmethod
[docs] def get_user_data(timeout=None, url=None, num_retries=None): """ Get instance user data :type timeout: int :param timeout: timeout for the request :type url: string :param url: metadata_service_url :type num_retries: int :param num_retries: how many times to retry :rtype: dict :return: instance user data as a dictionary """ if timeout is None: timeout = config.getint('Boto', 'http_socket_timeout', 70) if num_retries is None: num_retries = config.getint('Boto', 'num_retries', 5) if url is None: url = config.get( 'Boto', 'metadata_service_url', 'http://169.254.169.254') return get_userdata(timeout=timeout, url=url, num_retries=num_retries)
[docs] def get_credentials(self): """ Get AWS credentials from instance user-data :rtype: dict :return: AWS credentials as a dictionary """ try: access_key = self.user_data[ 'Credentials']['AWS_ACCESS_KEY_ID'] secret_key = self.user_data[ 'Credentials']['AWS_SECRET_ACCESS_KEY'] credentials = {'aws_access_key_id': access_key, 'aws_secret_access_key': secret_key} return credentials except KeyError: return None
[docs] def get_region(self): """ Get the region from instance meta-data :rtype: string :return: the region name """ try: return self.meta_data['placement'][ 'availability-zone'][:-1].strip() except KeyError: raise IcsMetaException( "Cannot find the 'region info' in meta-data.")
[docs] def get_zone(self): """ Get the availability zone from instance meta-data :rtype: string :return: the availability zone name """ try: return self.meta_data['placement'][ 'availability-zone'][-1].strip() except KeyError: raise IcsMetaException( "Cannot find the 'availability zone' in meta-data.")
[docs] def get_public_ip(self): """ Get the public ip address from instance meta-data :rtype: string :return: the public ip address """ try: self.meta_data = IcsMeta.get_meta_data() return self.meta_data["public-ipv4"] except KeyError: return None # raise IcsMetaException( # "Cannot find the 'public ip address' in meta-data.")
[docs] def get_private_ip(self): """ Get the private ip address from instance meta-data :rtype: string :return: the private ip address """ try: self.meta_data = IcsMeta.get_meta_data() return self.meta_data["local-ipv4"] except KeyError: return None
[docs] def get_public_hostname(self): """ Get the public hostname from instance meta-data :rtype: string :return: the public hostname """ try: self.meta_data = IcsMeta.get_meta_data() return self.meta_data["public-hostname"] except KeyError: raise IcsMetaException( 'Cannot find the public hostname in meta-data.')
[docs] def get_sns_topic(self): """ Get the SNS Topic from instance user-data :rtype: string :return: the SNS Topic name """ try: sns_topic = self.user_data['Bootstrap']['SNS_Topic'] return sns_topic except KeyError: raise IcsMetaException("Cannot find the 'SNS topic' in user-data.")
[docs] def get_cfg_bucket(self): """ Get the Config Bucket from instance user-data :rtype: string :return: the Config Bucket name """ try: cfg_bucket = self.user_data['S3']['ConfigBucket'] return cfg_bucket except KeyError: raise IcsMetaException( "Cannot find the 'Config Bucket' in user-data.")
[docs] def get_script_url(self): """ Get the S3 url for import scripts from instance user-data :rtype: string :return: the s3 url for scripts """ try: script_url = self.user_data['Bootstrap']['URL'] return script_url except KeyError: raise IcsMetaException( "Cannot find the 'URL' in user-data.")
[docs] def get_instance_id(self): """ Get the instance id from instance meta-data :rtype: string :return: the instance id """ try: return self.meta_data["instance-id"] except KeyError: raise IcsMetaException( "Cannot find the 'instance id' in meta-data.")
[docs] def get_openssh_pubkey(self): """ Get the openssh public key from instance meta-data :rtype: string :return: the contents of openssh public key """ try: return self.meta_data['public-keys'].values()[0][0] except KeyError: raise IcsMetaException( "Cannot find the 'openssh-key' in meta-data.")
[docs] def get_machine_tags(self, timeout=120): """ Get the instance tags :rtype: string :return: the tags of this instance """ region = self.get_region() instance_id = self.get_instance_id() if self.credentials is None: ec2conn = IcsEc2(region) else: ec2conn = IcsEc2(region, **self.credentials) for i in xrange(timeout / 5): result = ec2conn.get_instance_tags(instance_id) if result: return result time.sleep(5) else: # To avoid specific tags with "TypeError" Exception return {}
[docs] def get_eips_from_tag(self): """ Get the EIP list from instance tags :rtype: list :return: the list contains EIP addresses """ try: eiplist = self.tags['EIPList'] except KeyError: return None if eiplist is None: return None elif not isinstance(eiplist, basestring): return None if eiplist.startswith("s3://"): if self.credentials is None: s3conn = IcsS3() else: s3conn = IcsS3(**self.credentials) data = s3conn.get_file_as_string(eiplist) return re.split('[ \t\n,;]+', data.strip()) else: eips = re.split('[ \t\n,;]+', eiplist.strip()) results = [] for eip in eips: if is_valid_ip(eip): results.append(eip) if not results: return None else: return results
[docs] def get_dns_from_tag(self): """ Get the DnsName from instance tags :rtype: string :return: the DnsName """ try: return self.tags['DnsName'] except KeyError: return None
[docs] def get_role_name(self): """ Get the Role name from instance tags :rtype: string :return: the Role name """ try: return self.tags['Role'] except KeyError: return None
[docs] def get_instance_name(self): """ Get the Instance name from instance tags :rtype: string :return: the Instance name """ try: # Ensure the same case as the name of subfolder for S3 # configuration return self.tags['Name'].lower() # To avoid SNS Alert being not initialized except Exception: return None
[docs] def generate_hostname(self): """ Generate the hostname :rtype: string :return: the hostname """ try: return '-'.join([self.get_instance_name(), self.get_zone(), self.get_instance_id()[2:] ]) except KeyError: raise IcsMetaException( "Failed to generate instance hostname.")
[docs] def is_eip_ready(self, eip): """ check the readiness of the specified EIP address :type eip: string :param eip: one EIP address :rtype: boolean :return: True/False """ if eip != self.get_public_ip(): return False return True
[docs] def download_script(self, pattern): """ Download scripts from S3 :type pattern: string :param pattern: regrex expression to match :rtype: string :return: the local path where downloaded files stored """ if self.credentials is None: s3conn = IcsS3() else: s3conn = IcsS3(**self.credentials) script_uri = self.get_script_url() localpath = s3conn.batch_download(script_uri, pattern=pattern) return localpath
[docs] def download_cfg(self, pattern): """ Download configuration files from S3 :type pattern: string :param pattern: regrex expression to match :rtype: string :return: the local path where downloaded files stored """ if self.credentials is None: s3conn = IcsS3() else: s3conn = IcsS3(**self.credentials) rolecfg_uri = "s3://" + os.path.join(self.get_cfg_bucket(), self.get_role_name()) localpath = s3conn.batch_download(rolecfg_uri, pattern=pattern) instcfg_uri = os.path.join(rolecfg_uri, self.get_instance_name()) localpath.extend(s3conn.batch_download(instcfg_uri, pattern=pattern)) return localpath
[docs] def init_config(self): """ Combine meta-data, user-data, tags into one json string :rtype: dict :return: json string contains meta-data, user-data, tags """ data = {} data.update({'MetaData': self.meta_data}) data.update({'UserData': self.user_data}) data.update({'Tags': self.get_machine_tags()}) return data
[docs] def init_alert(self, prefix='ICS'): """ Intialize ICS Alert :type prefix: str :param prefix: prefix string to indicate which process :rtype: class :return: the instance of initialized IcsAlert class """ sns_region = self.get_region() sns_topic = self.get_sns_topic() instance_id = self.get_instance_id() instance_name = self.get_instance_name() if instance_name is None: msg_prefix = "%s|%s|%s" % (prefix, sns_region, instance_id) else: msg_prefix = "%s|%s|%s|%s" % (prefix, sns_region, instance_name, instance_id) if self.credentials is None: alert = IcsAlert(sns_region, sns_topic, msg_prefix) else: alert = IcsAlert( sns_region, sns_topic, msg_prefix, **self.credentials) log.info("Alert setup in SNS topic '%s' with the prefix '%s'" % (sns_topic, msg_prefix)) return alert # vim: tabstop=4 shiftwidth=4 softtabstop=4
Read the Docs v: latest
Versions
latest
Downloads
PDF
HTML
Epub
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.