hostname.py (7449B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\datadog\util\hostname.py 2 import socket 3 import re 4 import logging 5 import subprocess 6 import types 7 from datadog.util.compat import url_lib, is_p3k, iteritems, json 8 from datadog.util.config import get_config, get_os, CfgNotFound 9 VALID_HOSTNAME_RFC_1123_PATTERN = re.compile('^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$') 10 MAX_HOSTNAME_LEN = 255 11 log = logging.getLogger('datadog.api') 12 13 def is_valid_hostname(hostname): 14 if hostname.lower() in set(['localhost', 15 'localhost.localdomain', 16 'localhost6.localdomain6', 17 'ip6-localhost']): 18 log.warning('Hostname: %s is local' % hostname) 19 return False 20 if len(hostname) > MAX_HOSTNAME_LEN: 21 log.warning('Hostname: %s is too long (max length is %s characters)' % (hostname, MAX_HOSTNAME_LEN)) 22 return False 23 if VALID_HOSTNAME_RFC_1123_PATTERN.match(hostname) is None: 24 log.warning('Hostname: %s is not complying with RFC 1123' % hostname) 25 return False 26 return True 27 28 29 def get_hostname(): 30 hostname = None 31 config = None 32 try: 33 config = get_config() 34 config_hostname = config.get('hostname') 35 if config_hostname and is_valid_hostname(config_hostname): 36 return config_hostname 37 except CfgNotFound: 38 log.info('No agent or invalid configuration file found') 39 40 if hostname is None: 41 gce_hostname = GCE.get_hostname(config) 42 if gce_hostname is not None: 43 if is_valid_hostname(gce_hostname): 44 return gce_hostname 45 if hostname is None: 46 47 def _get_hostname_unix(): 48 try: 49 p = subprocess.Popen(['/bin/hostname', '-f'], stdout=subprocess.PIPE) 50 out, err = p.communicate() 51 if p.returncode == 0: 52 if is_p3k(): 53 return out.decode('utf-8').strip() 54 else: 55 return out.strip() 56 except Exception: 57 return None 58 59 os_name = get_os() 60 if os_name in ('mac', 'freebsd', 'linux', 'solaris'): 61 unix_hostname = _get_hostname_unix() 62 if unix_hostname and is_valid_hostname(unix_hostname): 63 hostname = unix_hostname 64 if hostname is not None and True in [ hostname.lower().startswith(p) for p in [u'ip-', u'domu'] ]: 65 instanceid = EC2.get_instance_id(config) 66 if instanceid: 67 hostname = instanceid 68 if hostname is None: 69 try: 70 socket_hostname = socket.gethostname() 71 except socket.error: 72 socket_hostname = None 73 74 if socket_hostname and is_valid_hostname(socket_hostname): 75 hostname = socket_hostname 76 if hostname is None: 77 log.warning(u'Unable to reliably determine host name. You can define one in your `hosts` file, or in `datadog.conf` file if you have Datadog Agent installed.') 78 return hostname 79 80 81 def get_ec2_instance_id(): 82 try: 83 old_timeout = socket.getdefaulttimeout() 84 socket.setdefaulttimeout(0.25) 85 try: 86 return url_lib.urlopen(url_lib.Request('http://169.254.169.254/latest/meta-data/instance-id')).read() 87 finally: 88 socket.setdefaulttimeout(old_timeout) 89 90 except: 91 return socket.gethostname() 92 93 94 class GCE(object): 95 URL = 'http://169.254.169.254/computeMetadata/v1/?recursive=true' 96 TIMEOUT = 0.1 97 SOURCE_TYPE_NAME = 'google cloud platform' 98 metadata = None 99 100 @staticmethod 101 def _get_metadata(agentConfig): 102 if GCE.metadata is not None: 103 return GCE.metadata 104 if not agentConfig['collect_instance_metadata']: 105 log.info('Instance metadata collection is disabled. Not collecting it.') 106 GCE.metadata = {} 107 return GCE.metadata 108 socket_to = None 109 try: 110 socket_to = socket.getdefaulttimeout() 111 socket.setdefaulttimeout(GCE.TIMEOUT) 112 except Exception: 113 pass 114 115 try: 116 opener = url_lib.build_opener() 117 opener.addheaders = [('X-Google-Metadata-Request', 'True')] 118 GCE.metadata = json.loads(opener.open(GCE.URL).read().strip()) 119 except Exception: 120 GCE.metadata = {} 121 122 try: 123 if socket_to is None: 124 socket_to = 3 125 socket.setdefaulttimeout(socket_to) 126 except Exception: 127 pass 128 129 return GCE.metadata 130 131 @staticmethod 132 def get_hostname(agentConfig): 133 try: 134 host_metadata = GCE._get_metadata(agentConfig) 135 return host_metadata['instance']['hostname'].split('.')[0] 136 except Exception: 137 return None 138 139 140 class EC2(object): 141 URL = 'http://169.254.169.254/latest/meta-data' 142 TIMEOUT = 0.1 143 metadata = {} 144 145 @staticmethod 146 def get_tags(agentConfig): 147 if not agentConfig['collect_instance_metadata']: 148 log.info('Instance metadata collection is disabled. Not collecting it.') 149 return [] 150 socket_to = None 151 try: 152 socket_to = socket.getdefaulttimeout() 153 socket.setdefaulttimeout(EC2.TIMEOUT) 154 except Exception: 155 pass 156 157 try: 158 iam_role = url_lib.urlopen(EC2.URL + '/iam/security-credentials').read().strip() 159 iam_params = json.loads(url_lib.urlopen(EC2.URL + '/iam/security-credentials' + '/' + str(iam_role)).read().strip()) 160 from boto.ec2.connection import EC2Connection 161 connection = EC2Connection(aws_access_key_id=iam_params['AccessKeyId'], aws_secret_access_key=iam_params['SecretAccessKey'], security_token=iam_params['Token']) 162 instance_object = connection.get_only_instances([EC2.metadata['instance-id']])[0] 163 EC2_tags = [ u'%s:%s' % (tag_key, tag_value) for tag_key, tag_value in iteritems(instance_object.tags) ] 164 except Exception: 165 log.exception('Problem retrieving custom EC2 tags') 166 EC2_tags = [] 167 168 try: 169 if socket_to is None: 170 socket_to = 3 171 socket.setdefaulttimeout(socket_to) 172 except Exception: 173 pass 174 175 return EC2_tags 176 177 @staticmethod 178 def get_metadata(agentConfig): 179 if not agentConfig['collect_instance_metadata']: 180 log.info('Instance metadata collection is disabled. Not collecting it.') 181 return {} 182 socket_to = None 183 try: 184 socket_to = socket.getdefaulttimeout() 185 socket.setdefaulttimeout(EC2.TIMEOUT) 186 except Exception: 187 pass 188 189 for k in ('instance-id', 'hostname', 'local-hostname', 'public-hostname', 'ami-id', 'local-ipv4', 'public-keys', 'public-ipv4', 'reservation-id', 'security-groups'): 190 try: 191 v = url_lib.urlopen(EC2.URL + '/' + str(k)).read().strip() 192 EC2.metadata[k] = v 193 except Exception: 194 pass 195 196 try: 197 if socket_to is None: 198 socket_to = 3 199 socket.setdefaulttimeout(socket_to) 200 except Exception: 201 pass 202 203 return EC2.metadata 204 205 @staticmethod 206 def get_instance_id(agentConfig): 207 try: 208 return EC2.get_metadata(agentConfig).get('instance-id', None) 209 except Exception: 210 return None