root / snfOCCI / APIserver.py @ c1106cd7
History | View | Annotate | Download (7.4 kB)
1 | c687b8f4 | John Giannelos | #!/usr/bin/env python
|
---|---|---|---|
2 | c687b8f4 | John Giannelos | |
3 | 0e9a6098 | John Giannelos | import re |
4 | c1106cd7 | John Giannelos | import sys |
5 | c1106cd7 | John Giannelos | from optparse import OptionParser, OptionValueError |
6 | 0e9a6098 | John Giannelos | import string |
7 | b92a3d98 | John Giannelos | import sqlite3 |
8 | b92a3d98 | John Giannelos | |
9 | ed91cac4 | John Giannelos | from snfOCCI.registry import snfRegistry |
10 | ed91cac4 | John Giannelos | from snfOCCI.compute import ComputeBackend |
11 | 088e4262 | John Giannelos | from snfOCCI.config import SERVER_CONFIG, KAMAKI_CONFIG |
12 | ed91cac4 | John Giannelos | |
13 | c687b8f4 | John Giannelos | from kamaki.clients.compute import ComputeClient |
14 | 4adfebfe | John Giannelos | from kamaki.clients.cyclades import CycladesClient |
15 | c687b8f4 | John Giannelos | from kamaki.config import Config |
16 | c687b8f4 | John Giannelos | |
17 | 77182fb8 | John Giannelos | from occi.core_model import Mixin, Resource |
18 | 22167a8c | John Giannelos | from occi.backend import MixinBackend |
19 | c687b8f4 | John Giannelos | from occi.extensions.infrastructure import COMPUTE, START, STOP, SUSPEND, RESTART, RESOURCE_TEMPLATE, OS_TEMPLATE |
20 | c687b8f4 | John Giannelos | from occi.wsgi import Application |
21 | 8619548c | John Giannelos | from occi.exceptions import HTTPError |
22 | c687b8f4 | John Giannelos | |
23 | c687b8f4 | John Giannelos | from wsgiref.simple_server import make_server |
24 | c687b8f4 | John Giannelos | from wsgiref.validate import validator |
25 | c687b8f4 | John Giannelos | |
26 | 8619548c | John Giannelos | import voms |
27 | c687b8f4 | John Giannelos | |
28 | c1106cd7 | John Giannelos | def parse_arguments(args): |
29 | c687b8f4 | John Giannelos | |
30 | c1106cd7 | John Giannelos | kw = {} |
31 | c1106cd7 | John Giannelos | kw["usage"] = "%prog [options]" |
32 | c1106cd7 | John Giannelos | kw["description"] = "OCCI interface to synnefo API" |
33 | c1106cd7 | John Giannelos | |
34 | c1106cd7 | John Giannelos | parser = OptionParser(**kw) |
35 | c1106cd7 | John Giannelos | parser.disable_interspersed_args() |
36 | c1106cd7 | John Giannelos | |
37 | c1106cd7 | John Giannelos | parser.add_option("--enable_voms", action="store_true", dest="enable_voms", default=False, help="Enable voms authorization") |
38 | c1106cd7 | John Giannelos | parser.add_option("--voms_db", action="store", type="string", dest="voms_db", help="Path to sqlite database file") |
39 | c1106cd7 | John Giannelos | |
40 | c1106cd7 | John Giannelos | (opts, args) = parser.parse_args(args) |
41 | c1106cd7 | John Giannelos | |
42 | c1106cd7 | John Giannelos | if opts.enable_voms and not opts.voms_db: |
43 | c1106cd7 | John Giannelos | print "--voms_db option required" |
44 | c1106cd7 | John Giannelos | parser.print_help() |
45 | c1106cd7 | John Giannelos | |
46 | c1106cd7 | John Giannelos | return (opts, args)
|
47 | b92a3d98 | John Giannelos | |
48 | c687b8f4 | John Giannelos | class MyAPP(Application): |
49 | c687b8f4 | John Giannelos | '''
|
50 | c687b8f4 | John Giannelos | An OCCI WSGI application.
|
51 | c687b8f4 | John Giannelos | '''
|
52 | c687b8f4 | John Giannelos | |
53 | 55ab2427 | John Giannelos | def refresh_images(self, snf, client): |
54 | b46572ab | John Giannelos | |
55 | 711721d6 | John Giannelos | images = snf.list_images() |
56 | 711721d6 | John Giannelos | for image in images: |
57 | 711721d6 | John Giannelos | IMAGE_ATTRIBUTES = {'occi.core.id': str(image['id'])} |
58 | 711721d6 | John Giannelos | IMAGE = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(image['name']), [OS_TEMPLATE], attributes = IMAGE_ATTRIBUTES) |
59 | b7fca2d2 | John Giannelos | self.register_backend(IMAGE, MixinBackend())
|
60 | 711721d6 | John Giannelos | |
61 | 55ab2427 | John Giannelos | def refresh_flavors(self, snf, client): |
62 | b7fca2d2 | John Giannelos | |
63 | 711721d6 | John Giannelos | flavors = snf.list_flavors() |
64 | 711721d6 | John Giannelos | for flavor in flavors: |
65 | 711721d6 | John Giannelos | details = snf.get_flavor_details(flavor['id'])
|
66 | 711721d6 | John Giannelos | FLAVOR_ATTRIBUTES = {'occi.core.id': flavor['id'], |
67 | 711721d6 | John Giannelos | 'occi.compute.cores': details['cpu'], |
68 | 711721d6 | John Giannelos | 'occi.compute.memory': details['ram'], |
69 | 711721d6 | John Giannelos | 'occi.storage.size': details['disk'], |
70 | 711721d6 | John Giannelos | } |
71 | 711721d6 | John Giannelos | FLAVOR = Mixin("http://schemas.ogf.org/occi/infrastructure#", str(flavor['name']), [RESOURCE_TEMPLATE], attributes = FLAVOR_ATTRIBUTES) |
72 | b7fca2d2 | John Giannelos | self.register_backend(FLAVOR, MixinBackend())
|
73 | b7fca2d2 | John Giannelos | |
74 | b7fca2d2 | John Giannelos | |
75 | 77182fb8 | John Giannelos | def refresh_compute_instances(self, snf): |
76 | dcb17973 | John Giannelos | '''Syncing registry with cyclades resources'''
|
77 | dcb17973 | John Giannelos | |
78 | 77182fb8 | John Giannelos | servers = snf.list_servers() |
79 | 77182fb8 | John Giannelos | snf_keys = [] |
80 | 77182fb8 | John Giannelos | for server in servers: |
81 | 77182fb8 | John Giannelos | snf_keys.append(str(server['id'])) |
82 | 77182fb8 | John Giannelos | |
83 | 77182fb8 | John Giannelos | resources = self.registry.resources
|
84 | 77182fb8 | John Giannelos | occi_keys = resources.keys() |
85 | 77182fb8 | John Giannelos | |
86 | 2bd4ca03 | John Giannelos | #Compute instances in synnefo not available in registry
|
87 | 77182fb8 | John Giannelos | diff = [x for x in snf_keys if '/compute/'+x not in occi_keys] |
88 | 77182fb8 | John Giannelos | for key in diff: |
89 | 77182fb8 | John Giannelos | |
90 | 77182fb8 | John Giannelos | details = snf.get_server_details(int(key))
|
91 | 77182fb8 | John Giannelos | flavor = snf.get_flavor_details(details['flavorRef'])
|
92 | 2bd4ca03 | John Giannelos | image = snf.get_image_details(details['imageRef'])
|
93 | 77182fb8 | John Giannelos | |
94 | 2bd4ca03 | John Giannelos | for i in self.registry.backends: |
95 | 2bd4ca03 | John Giannelos | if i.term == str(image['name']): |
96 | 2bd4ca03 | John Giannelos | rel_image = i |
97 | 2bd4ca03 | John Giannelos | if i.term == str(flavor['name']): |
98 | 2bd4ca03 | John Giannelos | rel_flavor = i |
99 | 2bd4ca03 | John Giannelos | |
100 | 2bd4ca03 | John Giannelos | resource = Resource(key, COMPUTE, [rel_flavor, rel_image]) |
101 | 77182fb8 | John Giannelos | resource.actions = [START] |
102 | 77182fb8 | John Giannelos | resource.attributes['occi.core.id'] = key
|
103 | 77182fb8 | John Giannelos | resource.attributes['occi.compute.state'] = 'inactive' |
104 | 77182fb8 | John Giannelos | resource.attributes['occi.compute.architecture'] = SERVER_CONFIG['compute_arch'] |
105 | 77182fb8 | John Giannelos | resource.attributes['occi.compute.cores'] = flavor['cpu'] |
106 | 77182fb8 | John Giannelos | resource.attributes['occi.compute.memory'] = flavor['ram'] |
107 | 77182fb8 | John Giannelos | resource.attributes['occi.compute.hostname'] = SERVER_CONFIG['hostname'] % {'id':int(key)} |
108 | 088e4262 | John Giannelos | |
109 | 77182fb8 | John Giannelos | self.registry.add_resource(key, resource, None) |
110 | 77182fb8 | John Giannelos | |
111 | 2bd4ca03 | John Giannelos | #Compute instances in registry not available in synnefo
|
112 | dcb17973 | John Giannelos | diff = [x for x in occi_keys if x[9:] not in snf_keys] |
113 | dcb17973 | John Giannelos | for key in diff: |
114 | dcb17973 | John Giannelos | self.registry.delete_resource(key, None) |
115 | dcb17973 | John Giannelos | |
116 | dcb17973 | John Giannelos | |
117 | b7fca2d2 | John Giannelos | def __call__(self, environ, response): |
118 | b7fca2d2 | John Giannelos | |
119 | b92a3d98 | John Giannelos | #Authorization
|
120 | 2bd4ca03 | John Giannelos | |
121 | c1106cd7 | John Giannelos | if ENABLE_VOMS:
|
122 | c1106cd7 | John Giannelos | |
123 | c1106cd7 | John Giannelos | global VOMS_DB
|
124 | c1106cd7 | John Giannelos | conn = sqlite3.connect(VOMS_DB) |
125 | 0e9a6098 | John Giannelos | |
126 | c1106cd7 | John Giannelos | ssl_dict = dict()
|
127 | c1106cd7 | John Giannelos | |
128 | c1106cd7 | John Giannelos | #Regular expression in HTTP headers
|
129 | c1106cd7 | John Giannelos | #raw environ[HTTP_SSL] contains PEM certificates in wrong format
|
130 | 4c9a536c | John Giannelos | |
131 | c1106cd7 | John Giannelos | pem_re = r'^(-----BEGIN CERTIFICATE----- )(.*|\s]*)( -----END CERTIFICATE-----)'
|
132 | 4c9a536c | John Giannelos | |
133 | c1106cd7 | John Giannelos | client_cert = re.search(pem_re, environ["HTTP_SSL_CLIENT_CERT"])
|
134 | c1106cd7 | John Giannelos | client_chain = re.search(pem_re, environ["HTTP_SSL_CLIENT_CERT_CHAIN_0"])
|
135 | 0e9a6098 | John Giannelos | |
136 | c1106cd7 | John Giannelos | client_cert_list=[] |
137 | c1106cd7 | John Giannelos | client_chain_list=[] |
138 | 0e9a6098 | John Giannelos | |
139 | c1106cd7 | John Giannelos | for i in range(1,4): |
140 | c1106cd7 | John Giannelos | client_cert_list.append(string.strip(client_cert.group(i))) |
141 | 0e9a6098 | John Giannelos | |
142 | c1106cd7 | John Giannelos | for i in range(1,4): |
143 | c1106cd7 | John Giannelos | client_chain_list.append(string.strip(client_chain.group(i))) |
144 | 0e9a6098 | John Giannelos | |
145 | 0e9a6098 | John Giannelos | |
146 | c1106cd7 | John Giannelos | cert = client_cert_list[0]+"\n"+client_cert_list[1].replace(" "," \n")+"\n"+client_cert_list[2] |
147 | c1106cd7 | John Giannelos | chain = client_chain_list[0]+"\n"+client_chain_list[1].replace(" "," \n")+"\n"+client_chain_list[2] |
148 | 0e9a6098 | John Giannelos | |
149 | c1106cd7 | John Giannelos | ssl_dict["SSL_CLIENT_S_DN"] = environ["HTTP_SSL_CLIENT_S_DN"] |
150 | c1106cd7 | John Giannelos | ssl_dict["SSL_CLIENT_CERT"] = cert
|
151 | c1106cd7 | John Giannelos | ssl_dict["SSL_CLIENT_CERT_CHAIN_0"] = chain
|
152 | 8619548c | John Giannelos | |
153 | c1106cd7 | John Giannelos | (user_dn, user_vo, user_fqans) = voms.authenticate(ssl_dict) |
154 | c1106cd7 | John Giannelos | print (user_dn, user_vo, user_fqans)
|
155 | 8619548c | John Giannelos | |
156 | c1106cd7 | John Giannelos | cursor = conn.cursor() |
157 | c1106cd7 | John Giannelos | query = "SELECT token FROM vo_map WHERE vo_name=?"
|
158 | c1106cd7 | John Giannelos | cursor.execute(query,[(user_vo)]) |
159 | 19f06355 | John Giannelos | |
160 | c1106cd7 | John Giannelos | (token,) = cursor.fetchone() |
161 | 19f06355 | John Giannelos | |
162 | c1106cd7 | John Giannelos | if token:
|
163 | c1106cd7 | John Giannelos | compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], token)
|
164 | c1106cd7 | John Giannelos | cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], token)
|
165 | 8619548c | John Giannelos | |
166 | c1106cd7 | John Giannelos | self.refresh_images(compClient,cyclClient)
|
167 | c1106cd7 | John Giannelos | self.refresh_flavors(compClient,cyclClient)
|
168 | c1106cd7 | John Giannelos | self.refresh_compute_instances(compClient)
|
169 | b92a3d98 | John Giannelos | |
170 | b92a3d98 | John Giannelos | |
171 | c1106cd7 | John Giannelos | return self._call_occi(environ, response, security = None, token = token, snf = compClient, client = cyclClient) |
172 | c1106cd7 | John Giannelos | else:
|
173 | c1106cd7 | John Giannelos | raise HTTPError(404, "Unauthorized access") |
174 | b92a3d98 | John Giannelos | |
175 | 8619548c | John Giannelos | else:
|
176 | c1106cd7 | John Giannelos | #Authorize with user token
|
177 | c1106cd7 | John Giannelos | compClient = ComputeClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN']) |
178 | c1106cd7 | John Giannelos | cyclClient = CycladesClient(KAMAKI_CONFIG['compute_url'], environ['HTTP_AUTH_TOKEN']) |
179 | c1106cd7 | John Giannelos | |
180 | c1106cd7 | John Giannelos | return self._call_occi(environ, response, security = None, token = environ['HTTP_AUTH_TOKEN'], snf = compClient, client = cyclClient) |
181 | 22167a8c | John Giannelos | |
182 | b92a3d98 | John Giannelos | |
183 | 43b14afb | John Giannelos | def main(): |
184 | 43b14afb | John Giannelos | |
185 | c1106cd7 | John Giannelos | global ENABLE_VOMS, VOMS_DB
|
186 | c1106cd7 | John Giannelos | (opts, args) = parse_arguments(sys.argv[1:])
|
187 | c1106cd7 | John Giannelos | |
188 | c1106cd7 | John Giannelos | ENABLE_VOMS = opts.enable_voms |
189 | c1106cd7 | John Giannelos | VOMS_DB = opts.voms_db |
190 | c1106cd7 | John Giannelos | |
191 | b46572ab | John Giannelos | APP = MyAPP(registry = snfRegistry()) |
192 | c687b8f4 | John Giannelos | |
193 | c1106cd7 | John Giannelos | COMPUTE_BACKEND = ComputeBackend() |
194 | c687b8f4 | John Giannelos | APP.register_backend(COMPUTE, COMPUTE_BACKEND) |
195 | c687b8f4 | John Giannelos | APP.register_backend(START, COMPUTE_BACKEND) |
196 | c687b8f4 | John Giannelos | APP.register_backend(STOP, COMPUTE_BACKEND) |
197 | c687b8f4 | John Giannelos | APP.register_backend(RESTART, COMPUTE_BACKEND) |
198 | c687b8f4 | John Giannelos | APP.register_backend(SUSPEND, COMPUTE_BACKEND) |
199 | c687b8f4 | John Giannelos | APP.register_backend(RESOURCE_TEMPLATE, MixinBackend()) |
200 | c687b8f4 | John Giannelos | APP.register_backend(OS_TEMPLATE, MixinBackend()) |
201 | c687b8f4 | John Giannelos | |
202 | c687b8f4 | John Giannelos | VALIDATOR_APP = validator(APP) |
203 | d7dfc401 | John Giannelos | HTTPD = make_server('', SERVER_CONFIG['port'], VALIDATOR_APP) |
204 | c687b8f4 | John Giannelos | HTTPD.serve_forever() |
205 | 43b14afb | John Giannelos |