7 import sfa.util.xmlrpcprotocol as xmlrpc
8 from unittest import TestCase
9 from optparse import OptionParser
10 from sfa.util.xmlrpcprotocol import ServerException
11 from sfa.util.namespace import *
12 from sfa.util.config import *
13 from sfa.trust.certificate import *
14 from sfa.trust.credential import *
15 from sfa.util.sfaticket import *
16 from sfa.util.rspec import *
17 from sfa.client import sfi
19 def random_string(size):
20 return "".join(random.sample(string.letters, size))
31 def __init__(self, options):
32 try: self.config = config = Config(options.config_file)
34 print "failed to read config_file %s" % options.config_file
36 key_path = os.path.dirname(options.config_file)
37 user_name = self.config.SFI_USER.split('.')[-1:][0]
38 key_file = key_path + os.sep + user_name + '.pkey'
39 cert_file = key_path + os.sep + user_name + '.cert'
40 self.key = Keypair(filename=key_file)
41 self.cert = Certificate(subject=self.config.SFI_USER)
42 self.cert.set_pubkey(self.key)
43 self.cert.set_issuer(self.key, self.config.SFI_USER)
45 self.cert.save_to_file(cert_file)
46 SFI_AGGREGATE = config.SFI_SM.replace('12347', '12346')
47 SFI_CM = 'http://' + options.cm_host + ':12346'
48 self.registry = xmlrpc.get_server(config.SFI_REGISTRY, key_file, cert_file)
49 self.aggregate = xmlrpc.get_server(SFI_AGGREGATE, key_file, cert_file)
50 self.sm = xmlrpc.get_server(config.SFI_SM, key_file, cert_file)
51 self.cm = xmlrpc.get_server(SFI_CM, key_file, cert_file)
52 self.hrn = config.SFI_USER
53 # XX defaulting to user, but this should be configurable so we can
54 # test from components persepctive
56 self.credential = self.get_credential(self.hrn)
58 def get_credential(self, hrn = None, type = 'user'):
59 if not hrn: hrn = self.hrn
61 cert = self.cert.save_to_string(save_parents=True)
62 request_hash = self.key.compute_hash([cert, 'user', hrn])
63 credential = self.registry.get_self_credential(cert, type, hrn, request_hash)
66 if not self.credential:
67 self.credential = self.get_credential(self.hrn, 'user')
68 return self.registry.get_credential(self.credential, type, hrn)
70 class BasicTestCase(unittest.TestCase):
71 def __init__(self, testname, client, test_slice=None):
72 unittest.TestCase.__init__(self, testname)
74 self.slice = test_slice
77 self.registry = self.client.registry
78 self.aggregate = self.client.aggregate
79 self.sm = self.client.sm
80 self.cm = self.client.cm
81 self.credential = self.client.credential
82 self.hrn = self.client.hrn
83 self.type = self.client.type
86 class RegistryTest(BasicTestCase):
90 Make sure test records dont exsit
92 BasicTestCase.setUp(self)
94 def testGetSelfCredential(self):
95 cred = self.client.get_credential()
96 # this will raise an openssl error if the credential string isnt valid
97 Credential(string=cred)
99 def testRegister(self):
100 authority = get_authority(self.hrn)
101 auth_cred = self.client.get_credential(authority, 'authority')
102 auth_record = {'hrn': '.'.join([authority, random_string(10).lower()]),
104 node_record = {'hrn': '.'.join([authority, random_string(10)]),
106 'hostname': random_string(6) + '.' + random_string(6)}
107 slice_record = {'hrn': '.'.join([authority, random_string(10)]),
108 'type': 'slice', 'researcher': [self.hrn]}
109 user_record = {'hrn': '.'.join([authority, random_string(10)]),
111 'email': random_string(6) +'@'+ random_string(5) +'.'+ random_string(3),
112 'first_name': random_string(7),
113 'last_name': random_string(7)}
115 all_records = [auth_record, node_record, slice_record, user_record]
116 for record in all_records:
118 self.registry.register(auth_cred, record)
119 self.registry.resolve(self.credential, record['hrn'])
123 try: self.registry.remove(auth_cred, record['type'], record['hrn'])
127 def testRegisterPeerObject(self):
130 def testUpdate(self):
131 authority = get_authority(self.hrn)
132 auth_cred = self.client.get_credential(authority, 'authority')
133 records = self.registry.resolve(self.credential, self.hrn)
134 if not records: assert False
136 self.registry.update(auth_cred, record)
138 def testResolve(self):
139 authority = get_authority(self.hrn)
140 self.registry.resolve(self.credential, self.hrn)
142 def testRemove(self):
143 authority = get_authority(self.hrn)
144 auth_cred = self.client.get_credential(authority, 'authority')
145 record = {'hrn': ".".join([authority, random_string(10)]),
147 self.registry.register(auth_cred, record)
148 self.registry.remove(auth_cred, record['type'], record['hrn'])
149 # should generate an exception
151 self.registry.resolve(self.credential, record['hrn'])
156 def testRemovePeerObject(self):
160 authority = get_authority(self.client.hrn)
161 self.registry.list(self.credential, authority)
163 def testGetRegistries(self):
164 self.registry.get_registries(self.credential)
166 def testGetAggregates(self):
167 self.registry.get_aggregates(self.credential)
169 def testGetTrustedCerts(self):
170 # this should fail unless we are a node
171 callable = self.registry.get_trusted_certs
172 server_exception = False
174 callable(self.credential)
175 except ServerException:
176 server_exception = True
178 if self.type in ['user'] and not server_exception:
182 class AggregateTest(BasicTestCase):
184 BasicTestCase.setUp(self)
186 def testGetSlices(self):
187 self.aggregate.get_slices(self.credential)
189 def testGetResources(self):
190 # available resources
191 agg_rspec = self.aggregate.get_resources(self.credential)
192 # resources used by a slice
193 slice_rspec = self.aggregate.get_resources(self.credential, self.slice['hrn'])
194 # will raise an exception if the rspec isnt valid
196 RSpec(xml=slice_rspec)
198 def testCreateSlice(self):
199 # get availabel resources
200 rspec = self.aggregate.get_resources(self.credential)
201 slice_credential = self.client.get_credential(self.slice['hrn'], 'slice')
202 self.aggregate.create_slice(slice_credential, self.slice['hrn'], rspec)
204 def testDeleteSlice(self):
205 slice_credential = self.client.get_credential(self.slice['hrn'], 'slice')
206 self.aggregate.delete_slice(slice_credential, self.slice['hrn'])
208 def testGetTicket(self):
209 slice_credential = self.client.get_credential(self.slice['hrn'], 'slice')
210 rspec = self.aggregate.get_resources(self.credential)
211 ticket = self.aggregate.get_ticket(slice_credential, self.slice['hrn'], rspec)
212 # will raise an exception if the ticket inst valid
213 SfaTicket(string=ticket)
215 class SlicemgrTest(AggregateTest):
217 AggregateTest.setUp(self)
219 # force calls to go through slice manager
220 self.aggregate = self.sm
222 # get the slice credential
225 class ComponentTest(BasicTestCase):
227 BasicTestCase.setUp(self)
228 self.slice_cred = self.client.get_credential(self.slice['hrn'], 'slice')
230 def testStartSlice(self):
231 self.cm.start_slice(self.slice_cred, self.slice['hrn'])
233 def testStopSlice(self):
234 self.cm.stop_slice(self.slice_cred, self.slice['hrn'])
236 def testDeleteSlice(self):
237 self.cm.delete_slice(self.slice_cred, self.slice['hrn'])
239 def testRestartSlice(self):
240 self.cm.restart_slice(self.slice_cred, self.slice['hrn'])
242 def testGetSlices(self):
243 self.cm.get_slices(self.slice_cred, self.slice['hrn'])
245 def testRedeemTicket(self):
246 rspec = self.aggregate.get_resources(self.credential)
247 ticket = self.aggregate.get_ticket(slice_cred, self.slice['hrn'], rspec)
248 self.cm.redeem_ticket(slice_cred, ticket)
251 def test_names(testcase):
252 return [name for name in dir(testcase) if name.startswith('test')]
254 def create_slice(client):
255 # register a slice that will be used for some test
256 authority = get_authority(client.hrn)
257 auth_cred = client.get_credential(authority, 'authority')
258 slice_record = {'hrn': ".".join([authority, random_string(10)]),
259 'type': 'slice', 'researcher': [client.hrn]}
260 client.registry.register(auth_cred, slice_record)
263 def delete_slice(cleint, slice):
264 authority = get_authority(client.hrn)
265 auth_cred = client.get_credential(authority, 'authority')
267 client.registry.remove(auth_cred, 'slice', slice['hrn'])
269 if __name__ == '__main__':
273 default_config_dir = os.path.expanduser('~/.sfi/sfi_config')
274 default_cm = "echo.cs.princeton.edu"
275 parser = OptionParser(usage="%(prog_name)s [options]" % locals())
276 parser.add_option('-f', '--config_file', dest='config_file', default=default_config_dir,
277 help='config file. default is %s' % default_config_dir)
278 parser.add_option('-r', '--registry', dest='registry', action='store_true',
279 default=False, help='run registry tests')
280 parser.add_option('-a', '--aggregate', dest='aggregate', action='store_true',
281 default=False, help='run aggregate tests')
282 parser.add_option('-s', '--slicemgr', dest='slicemgr', action='store_true',
283 default=False, help='run slicemgr tests')
284 parser.add_option('-c', '--component', dest='component', action='store_true',
285 default=False, help='run component tests')
286 parser.add_option('-d', '--cm_host', dest='cm_host', default=default_cm,
287 help='dns name of component to test. default is %s' % default_cm)
288 parser.add_option('-A', '--all', dest='all', action='store_true',
289 default=False, help='run component tests')
291 options, args = parser.parse_args()
292 suite = unittest.TestSuite()
293 client = Client(options)
296 # create the test slice if necessary
297 if options.all or options.slicemgr or options.aggregate \
298 or options.component:
299 test_slice = create_slice(client)
301 if options.registry or options.all:
302 for name in test_names(RegistryTest):
303 suite.addTest(RegistryTest(name, client))
305 if options.aggregate or options.all:
306 for name in test_names(AggregateTest):
307 suite.addTest(AggregateTest(name, client, test_slice))
309 if options.slicemgr or options.all:
310 for name in test_names(SlicemgrTest):
311 suite.addTest(SlicemgrTest(name, client, test_slice))
313 if options.component or options.all:
314 for name in test_names(ComponentTest):
315 suite.addTest(ComponentTest(name, client, test_slice))
318 unittest.TextTestRunner(verbosity=2).run(suite)
321 delete_slice(client, test_slice)