Updating trunk VERSION from 978.0 to 979.0
[chromium-blink-merge.git] / remoting / tools / hostdir.py
blobd8ef5cde52fd465b647b442f3644686606dbe2cd
1 #!/usr/bin/env python
3 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 # Chromoting Directory API client implementation. Used for testing/debugging
8 # purposes. Requires Python 2.6: json module is not available in earlier
9 # versions.
11 import os
12 import httplib
13 import json
14 import urllib
15 import urllib2
16 import random
17 import sys
19 DEFAULT_DIRECTORY_SERVER = 'www.googleapis.com'
21 auth_filepath = os.path.join(os.path.expanduser('~'),
22 '.chromotingDirectoryAuthToken')
24 def random_uuid():
25 return ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x" %
26 tuple(map(lambda x: random.randrange(0,65536), range(8))))
28 class Host:
29 def __init__(self, parameters=None):
30 if parameters != None:
31 self.host_id = parameters[u"hostId"]
32 self.host_name = parameters[u"hostName"]
33 self.public_key = parameters[u"publicKey"]
34 # Following fields may be missing, use get() for them.
35 self.jabber_id = parameters.get(u"jabberId")
36 self.created_time = parameters.get(u"createdTime")
37 self.updated_time = parameters.get(u"updatedTime")
38 self.status = parameters.get(u"status")
39 else:
40 self.host_id = random_uuid()
41 import socket
42 self.host_name = socket.gethostname()
43 self.public_key = None
44 self.jabber_id = None
45 self.created_time = None
46 self.updated_time = None
47 self.status = None
49 class HostDirectoryError(Exception):
50 def __init__(self, message, response):
51 Exception.__init__(self, message)
52 print response
53 self._response = response
55 class HostDirectory:
56 def __init__(self, username, auth_token, server=DEFAULT_DIRECTORY_SERVER):
57 self._username = username
58 self._auth_token = auth_token
59 self._base_url = '/chromoting/v1/@me/hosts'
61 self._http = httplib.HTTPSConnection(server)
62 self._headers = {"Authorization": "GoogleLogin auth=" + self._auth_token,
63 "Content-Type": "application/json" }
65 def add_host(self, host):
66 host_json = { 'data':
67 { 'hostId': host.host_id,
68 'hostName': host.host_name,
69 'publicKey': host.public_key,
72 if host.jabber_id:
73 host_json['data']['jabberId'] = host.jabber_id
74 post_data = json.dumps(host_json)
75 self._http.request("POST", self._base_url, post_data, self._headers)
76 response = self._http.getresponse()
77 if response.status != 200:
78 raise HostDirectoryError(response.reason, response.read())
79 data = response.read()
81 def get_hosts(self):
82 self._http.request("GET", self._base_url, headers=self._headers)
83 response = self._http.getresponse()
84 if response.status != 200:
85 raise HostDirectoryError(response.reason, response.read())
86 data = response.read()
87 data = json.loads(data)[u'data']
88 results = []
89 if data.has_key(u'items'):
90 for item in data[u'items']:
91 results.append(Host(item))
92 return results
94 def delete_host(self, host_id):
95 url = self._base_url + '/' + host_id
96 self._http.request("DELETE", url, headers=self._headers)
97 response = self._http.getresponse()
98 if response.status / 100 != 2: # Normally 204 is returned
99 raise HostDirectoryError(response.reason, response.read())
100 data = response.read()
102 def usage():
103 sys.stderr.write(
104 ("Usage:\n" +
105 " Login: \t\t%(cmd)s login\n" +
106 " Register host: \t%(cmd)s insert --hostId=<hostId>" +
107 " --hostName=<hostName> \\\n" +
108 "\t\t\t --publicKey=<publicKey> --jabberId=<jabberId>\n" +
109 " List hosts: \t\t%(cmd)s list\n" +
110 " Delete a host: \t%(cmd)s delete <host_id>\n")
111 % {"cmd" : sys.argv[0]})
112 return 1
114 class CommandError(Exception):
115 def __init__(self, message):
116 Exception.__init__(self, message)
118 def load_auth_token():
119 try:
120 lines = open(auth_filepath).readlines()
121 except IOError as e:
122 raise CommandError("Can't open file (%s). Please run " +
123 "'%s login' and try again." %
124 (auth_filepath, sys.argv[0]))
125 if len(lines) != 2:
126 raise CommandError("Invalid auth file (%s). Please run " +
127 "'%s login' and try again." %
128 (auth_filepath, sys.argv[0]))
129 return map(lambda x: x.strip(), lines)
131 def login_cmd(args):
132 """login command"""
133 if len(args) != 0:
134 return usage()
136 import getpass
137 import gaia_auth
139 print "Email:",
140 email = raw_input()
141 passwd = getpass.getpass("Password: ")
143 authenticator = gaia_auth.GaiaAuthenticator('chromoting');
144 auth_token = authenticator.authenticate(email, passwd)
146 # Set permission mask for created file.
147 os.umask(0066)
148 auth_file = open(auth_filepath, 'w')
149 auth_file.write(email)
150 auth_file.write('\n')
151 auth_file.write(auth_token)
152 auth_file.close()
154 print 'Auth token: ', auth_token
155 print '...saved in', auth_filepath
157 def list_cmd(args):
158 """list command"""
159 if len(args) != 0:
160 return usage()
161 (username, token) = load_auth_token()
162 client = HostDirectory(username, token)
163 print '%36s %30s %s' % ("HOST ID", "HOST NAME", "JABBER ID")
164 for host in client.get_hosts():
165 print '%36s %30s %s' % (host.host_id, host.host_name, host.jabber_id)
166 return 0
168 def insert_cmd(args):
169 """insert command"""
170 (username, token) = load_auth_token()
171 client = HostDirectory(username, token)
173 host = Host()
174 for arg in args:
175 if arg.startswith("--hostId="):
176 host.host_id = arg[len("--hostId="):]
177 elif arg.startswith("--hostName="):
178 host.host_name = arg[len("--hostName="):]
179 elif arg.startswith("--publicKey="):
180 host.public_key = arg[len("--publicKey="):]
181 elif arg.startswith("--jabberId="):
182 host.jabber_id = arg[len("--jabberId="):]
183 else:
184 return usage()
186 client.add_host(host)
187 return 0
189 def delete_cmd(args):
190 """delete command"""
191 if len(args) != 1:
192 return usage()
193 host_id = args[0]
194 (username, token) = load_auth_token()
195 client = HostDirectory(username, token)
196 client.delete_host(host_id)
197 return 0
199 def main():
200 import sys
201 args = sys.argv[1:]
202 if len(args) == 0:
203 return usage()
204 command = args[0]
206 try:
207 if command == "help":
208 usage()
209 elif command == "login":
210 return login_cmd(args[1:])
211 elif command == "list":
212 return list_cmd(args[1:])
213 elif command == "insert":
214 return insert_cmd(args[1:])
215 elif command == "delete":
216 return delete_cmd(args[1:])
217 else:
218 raise CommandError("Unknown command: %s" % command);
220 except CommandError as e:
221 sys.stderr.write("%s\n" % e.args[0])
222 return 1
224 return 0
226 if __name__ == '__main__':
227 sys.exit(main())