summaryrefslogtreecommitdiff
path: root/tools/mock-meta.py
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2012-07-03 12:46:55 -0700
committerJoshua Harlow <harlowja@yahoo-inc.com>2012-07-03 12:46:55 -0700
commit21117bb5c26abcb42a7dcc5f318190e734c849bd (patch)
treef4c7d8d484681557defb00519296c33b07775b8d /tools/mock-meta.py
parent7e1a250d70c39607bc1f3e3134d6331cd372f511 (diff)
downloadvyos-cloud-init-21117bb5c26abcb42a7dcc5f318190e734c849bd.tar.gz
vyos-cloud-init-21117bb5c26abcb42a7dcc5f318190e734c849bd.zip
1. Update the mock ec2 data with some of the pubkey code from smosers ec2 metadata server.
2. Allow the setting of the ip addr (not just to 0.0.0.0) 3. Add comment as to how to use this for the 169 'magic' addr
Diffstat (limited to 'tools/mock-meta.py')
-rwxr-xr-xtools/mock-meta.py78
1 files changed, 70 insertions, 8 deletions
diff --git a/tools/mock-meta.py b/tools/mock-meta.py
index 5f421c98..7c38ec48 100755
--- a/tools/mock-meta.py
+++ b/tools/mock-meta.py
@@ -4,6 +4,19 @@
#
# http://docs.amazonwebservices.com/AWSEC2/2007-08-29/DeveloperGuide/AESDG-chapter-instancedata.html
+"""
+To use this to mimic the EC2 metadata service entirely, run it like:
+ # Where 'eth0' is *some* interface.
+ sudo ifconfig eth0:0 169.254.169.254 netmask 255.255.255.255
+
+ sudo ./mock-meta -a 169.254.169.254 -p 80
+
+Then:
+ wget -q http://169.254.169.254/latest/meta-data/instance-id -O -; echo
+ curl --silent http://169.254.169.254/latest/meta-data/instance-id ; echo
+ ec2metadata --instance-id
+"""
+
import functools
import httplib
import json
@@ -20,7 +33,6 @@ from BaseHTTPServer import (HTTPServer, BaseHTTPRequestHandler)
log = logging.getLogger('meta-server')
-# Constants
EC2_VERSIONS = [
'1.0',
'2007-01-19',
@@ -69,6 +81,14 @@ META_CAPABILITIES = [
'security-groups'
]
+PUB_KEYS = {
+ 'brickies': [
+ 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3I7VUf2l5gSn5uavROsc5HRDpZdQueUq5ozemNSj8T7enqKHOEaFoU2VoPgGEWC9RyzSQVeyD6s7APMcE82EtmW4skVEgEGSbDc1pvxzxtchBj78hJP6Cf5TCMFSXw+Fz5rF1dR23QDbN1mkHs7adr8GW4kSWqU7Q7NDwfIrJJtO7Hi42GyXtvEONHbiRPOe8stqUly7MvUoN+5kfjBM8Qqpfl2+FNhTYWpMfYdPUnE7u536WqzFmsaqJctz3gBxH9Ex7dFtrxR4qiqEr9Qtlu3xGn7Bw07/+i1D+ey3ONkZLN+LQ714cgj8fRS4Hj29SCmXp5Kt5/82cD/VN3NtHw== brickies',
+ '',
+ ],
+}
+
+
INSTANCE_TYPES = [
'm1.small',
'm1.medium',
@@ -136,6 +156,8 @@ class MetaDataHandler(object):
def get_data(self, params, who, **kwargs):
if not params:
+ # Show the root level capabilities when
+ # no params are passed...
caps = sorted(META_CAPABILITIES)
return "\n".join(caps)
action = params[0]
@@ -172,6 +194,43 @@ class MetaDataHandler(object):
return "r-%s" % (id_generator(lower=True))
elif action == 'product-codes':
return "%s" % (id_generator(size=8))
+ elif action == 'public-keys':
+ nparams = params[1:]
+ # public-keys is messed up. a list of /latest/meta-data/public-keys/
+ # shows something like: '0=brickies'
+ # but a GET to /latest/meta-data/public-keys/0=brickies will fail
+ # you have to know to get '/latest/meta-data/public-keys/0', then
+ # from there you get a 'openssh-key', which you can get.
+ # this hunk of code just re-works the object for that.
+ key_ids = sorted(list(PUB_KEYS.keys()))
+ if nparams:
+ mybe_key = nparams[0]
+ try:
+ key_id = int(mybe_key)
+ key_name = key_ids[key_id]
+ except:
+ raise WebException(httplib.BAD_REQUEST, "Unknown key id %r" % mybe_key)
+ # Extract the possible sub-params
+ key_info = {
+ "openssh-key": "\n".join(PUB_KEYS[key_name]),
+ }
+ result = dict(key_info)
+ for k in nparams[1:]:
+ try:
+ result = result.get(k)
+ except (AttributeError, TypeError):
+ result = None
+ break
+ if isinstance(result, (dict)):
+ result = json.dumps(result)
+ if result is None:
+ result = ''
+ return str(result)
+ else:
+ contents = []
+ for (i, key_id) in enumerate(key_ids):
+ contents.append("%s=%s" % (i, key_id))
+ return "\n".join(contents)
elif action == 'placement':
nparams = params[1:]
if not nparams:
@@ -198,10 +257,8 @@ class UserDataHandler(object):
def _get_user_blob(self, **kwargs):
blob = None
- if self.opts['user_data_file']:
- with open(opts['user_data_file'], 'rb') as fh:
- blob = fh.read()
- blob = blob.strip()
+ if self.opts['user_data_file'] is not None:
+ blob = self.opts['user_data_file']
if not blob:
blob_mp = {
'hostname': kwargs.get('who', 'localhost'),
@@ -312,6 +369,8 @@ def extract_opts():
parser = OptionParser()
parser.add_option("-p", "--port", dest="port", action="store", type=int, default=80,
help="port from which to serve traffic (default: %default)", metavar="PORT")
+ parser.add_option("-a", "--addr", dest="address", action="store", type=str, default='0.0.0.0',
+ help="address from which to serve traffic (default: %default)", metavar="ADDRESS")
parser.add_option("-f", '--user-data-file', dest='user_data_file', action='store',
help="user data filename to serve back to incoming requests", metavar='FILE')
(options, args) = parser.parse_args()
@@ -319,10 +378,12 @@ def extract_opts():
out['extra'] = args
out['port'] = options.port
out['user_data_file'] = None
+ out['address'] = options.address
if options.user_data_file:
if not os.path.isfile(options.user_data_file):
parser.error("Option -f specified a non-existent file")
- out['user_data_file'] = options.user_data_file
+ with open(options.user_data_file, 'rb') as fh:
+ out['user_data_file'] = fh.read()
return out
@@ -340,9 +401,10 @@ def run_server():
setup_logging(logging.DEBUG)
setup_fetchers(opts)
log.info("CLI opts: %s", opts)
- server = HTTPServer(('0.0.0.0', opts['port']), Ec2Handler)
+ server_address = (opts['address'], opts['port'])
+ server = HTTPServer(server_address, Ec2Handler)
sa = server.socket.getsockname()
- log.info("Serving server on %s using port %s ...", sa[0], sa[1])
+ log.info("Serving ec2 metadata on %s using port %s ...", sa[0], sa[1])
server.serve_forever()