1import unittest
2import uuid
3from TestInput import TestInput, TestInputSingleton
4import logger
5import datetime
6import time
7from membase.api.exception import BucketCreationException
8from membase.api.rest_client import RestConnection
9from membase.helper.bucket_helper import BucketOperationHelper
10
11class CreateMembaseBucketsTests(unittest.TestCase):
12    version = None
13    servers = None
14    input = TestInput
15    log = None
16
17    #as part of the setup let's delete all the existing buckets
18    def setUp(self):
19        self.log = logger.Logger.get_logger()
20        self.input = TestInputSingleton.input
21        self.assertTrue(self.input, msg="input parameters missing...")
22        self.servers = self.input.servers
23        BucketOperationHelper.delete_all_buckets_or_assert(servers=self.servers, test_case=self)
24        self._log_start()
25
26    def tearDown(self):
27        BucketOperationHelper.delete_all_buckets_or_assert(servers=self.servers, test_case=self)
28        self._log_finish()
29
30
31    def _log_start(self):
32        try:
33            msg = "{0} : {1} started ".format(datetime.datetime.now(), self._testMethodName)
34            RestConnection(self.servers[0]).log_client_error(msg)
35        except:
36            pass
37
38
39    def _log_finish(self):
40        try:
41            msg = "{0} : {1} finished ".format(datetime.datetime.now(), self._testMethodName)
42            RestConnection(self.servers[0]).log_client_error(msg)
43        except:
44            pass
45
46    # read each server's version number and compare it to self.version
47    def test_default_moxi(self):
48        name = 'default'
49        for serverInfo in self.servers:
50            rest = RestConnection(serverInfo)
51            proxyPort = rest.get_nodes_self().moxi + 1000
52            rest.create_bucket(bucket=name, ramQuotaMB=200, proxyPort=proxyPort)
53            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
54            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
55
56    def test_default_case_sensitive_dedicated(self):
57        name = 'Default'
58        for serverInfo in self.servers:
59            rest = RestConnection(serverInfo)
60            proxyPort = rest.get_nodes_self().moxi
61            rest.create_bucket(bucket=name,
62                               ramQuotaMB=200,
63                               authType='sasl',
64                               saslPassword='test_non_default',
65                               proxyPort=proxyPort)
66            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
67            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
68
69            name = 'default'
70
71            try:
72                rest.create_bucket(bucket=name,
73                                   ramQuotaMB=200,
74                                   proxyPort=11221,
75                                   authType='sasl',
76                                   saslPassword='test_non_default')
77                msg = "create_bucket created two buckets in different case : {0},{1}".format('default', 'Default')
78                self.fail(msg)
79            except BucketCreationException as ex:
80            #check if 'default' and 'Default' buckets exist
81                self.log.info('BucketCreationException was thrown as expected')
82                self.log.info(ex.message)
83
84    def test_default_on_non_default_port(self):
85        name = 'default'
86        for serverInfo in self.servers:
87            rest = RestConnection(serverInfo)
88            proxyPort = rest.get_nodes_self().moxi + 1000
89            rest.create_bucket(bucket=name,
90                               ramQuotaMB=200,
91                               proxyPort=proxyPort,
92                               authType='sasl',
93                               saslPassword='test_non_default')
94            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
95            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
96
97
98    def test_non_default_moxi(self):
99        name = 'test_non_default'
100        for serverInfo in self.servers:
101            rest = RestConnection(serverInfo)
102            proxyPort = rest.get_nodes_self().moxi + 400
103            rest.create_bucket(bucket=name,
104                               ramQuotaMB=200,
105                               proxyPort=proxyPort)
106            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
107            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
108
109    def test_default_case_sensitive_different_ports(self):
110        name = 'default'
111        for serverInfo in self.servers:
112            rest = RestConnection(serverInfo)
113            proxyPort = rest.get_nodes_self().moxi + 500
114            rest.create_bucket(bucket=name,
115                               ramQuotaMB=200,
116                               proxyPort=proxyPort)
117            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
118            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
119
120            try:
121                name = 'DEFAULT'
122                rest.create_bucket(bucket=name, ramQuotaMB=200, proxyPort=proxyPort + 1000)
123                msg = "create_bucket created two buckets in different case : {0},{1}".format('default', 'DEFAULT')
124                self.fail(msg)
125            except BucketCreationException as ex:
126                #check if 'default' and 'Default' buckets exist
127                self.log.info('BucketCreationException was thrown as expected')
128                self.log.info(ex.message)
129
130
131    def test_non_default_case_sensitive_different_port(self):
132        postfix = uuid.uuid4()
133        lowercase_name = 'uppercase_{0}'.format(postfix)
134        for serverInfo in self.servers:
135            rest = RestConnection(serverInfo)
136            proxyPort = rest.get_nodes_self().moxi + 500
137            rest.create_bucket(bucket=lowercase_name,
138                               ramQuotaMB=200,
139                               proxyPort=proxyPort)
140            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(lowercase_name)
141            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(lowercase_name, rest), msg=msg)
142
143            uppercase_name = 'UPPERCASE_{0}'.format(postfix)
144            try:
145                rest.create_bucket(bucket=uppercase_name,
146                                   ramQuotaMB=200,
147                                   proxyPort=proxyPort + 1000)
148                msg = "create_bucket created two buckets in different case : {0},{1}".format(lowercase_name,
149                                                                                             uppercase_name)
150                self.fail(msg)
151            except BucketCreationException as ex:
152                #check if 'default' and 'Default' buckets exist
153                self.log.info('BucketCreationException was thrown as expected')
154                self.log.info(ex.message)
155
156    def test_non_default_case_sensitive_same_port(self):
157        postfix = uuid.uuid4()
158        name = 'uppercase_{0}'.format(postfix)
159        for serverInfo in self.servers:
160            rest = RestConnection(serverInfo)
161            proxyPort = rest.get_nodes_self().moxi + 100
162            rest.create_bucket(bucket=name,
163                               ramQuotaMB=200,
164                               proxyPort=proxyPort)
165            msg = 'create_bucket succeeded but bucket {0} does not exist'.format(name)
166            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
167
168            self.log.info("user should not be able to create a new bucket on a an already used port")
169            name = 'UPPERCASE{0}'.format(postfix)
170            try:
171                rest.create_bucket(bucket=name,
172                                   ramQuotaMB=200,
173                                   proxyPort=proxyPort)
174                self.fail('create-bucket did not throw exception while creating a new bucket on an already used port')
175            #make sure it raises bucketcreateexception
176            except BucketCreationException as ex:
177                self.log.error(ex)
178
179    def test_less_than_minimum_memory_quota(self):
180        postfix = uuid.uuid4()
181        name = 'minmemquota_{0}'.format(postfix)
182        for serverInfo in self.servers:
183            rest = RestConnection(serverInfo)
184            proxyPort = rest.get_nodes_self().moxi
185            try:
186                rest.create_bucket(bucket=name, ramQuotaMB=99, authType='sasl', proxyPort=proxyPort)
187                self.fail('create-bucket did not throw exception while creating a new bucket with 99 MB quota')
188            #make sure it raises bucketcreateexception
189            except BucketCreationException as ex:
190                self.log.error(ex)
191
192            try:
193                rest.create_bucket(bucket=name, ramQuotaMB=0,
194                                   authType='sasl', proxyPort=proxyPort)
195
196                self.fail('create-bucket did not throw exception while creating a new bucket with 0 MB quota')
197            #make sure it raises bucketcreateexception
198            except BucketCreationException as ex:
199                self.log.info(ex)
200
201    def test_max_memory_quota(self):
202        postfix = uuid.uuid4()
203        name = 'maxquota_{0}'.format(postfix)
204        for serverInfo in self.servers:
205            rest = RestConnection(serverInfo)
206            info = rest.get_nodes_self()
207            proxyPort = rest.get_nodes_self().moxi
208            bucket_ram = info.memoryQuota
209            try:
210                rest.create_bucket(bucket=name,
211                                   ramQuotaMB=bucket_ram,
212                                   authType='sasl',
213                                   proxyPort=proxyPort)
214            except BucketCreationException as ex:
215                self.log.error(ex)
216                self.fail('failed to create bucket with max ram per node')
217
218            msg = 'failed to start up bucket with max ram per node'
219            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
220
221    def test_negative_replica(self):
222        postfix = uuid.uuid4()
223        name = '-1replica_{0}'.format(postfix)
224        for serverInfo in self.servers:
225            rest = RestConnection(serverInfo)
226            proxyPort = rest.get_nodes_self().moxi
227            try:
228                rest.create_bucket(bucket=name,
229                                   ramQuotaMB=200,
230                                   replicaNumber=-1,
231                                   authType='sasl',
232                                   proxyPort=proxyPort)
233                self.fail('bucket create succeded even with a negative replica count')
234            except BucketCreationException as ex:
235                self.log.info(ex)
236
237    def test_zero_replica(self):
238        postfix = uuid.uuid4()
239        name = 'replica_{0}'.format(postfix)
240        for serverInfo in self.servers:
241            rest = RestConnection(serverInfo)
242            proxyPort = rest.get_nodes_self().moxi
243            try:
244                rest.create_bucket(bucket=name,
245                                   ramQuotaMB=200,
246                                   replicaNumber=0,
247                                   authType='sasl', proxyPort=proxyPort)
248            except BucketCreationException as ex:
249                self.log.error(ex)
250                self.fail('failed to create bucket with 0 replicas')
251
252            msg = 'failed to start up bucket with 0 replicas'
253            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
254
255    def test_one_replica(self):
256        postfix = uuid.uuid4()
257        name = 'replica_{0}'.format(postfix)
258        for serverInfo in self.servers:
259            rest = RestConnection(serverInfo)
260            proxyPort = rest.get_nodes_self().moxi
261            try:
262                rest.create_bucket(bucket=name, ramQuotaMB=200, authType='sasl', proxyPort=proxyPort)
263            except BucketCreationException as ex:
264                self.log.error(ex)
265                self.fail('failed to create bucket with 1 replicas')
266
267            msg = 'failed to start up bucket with 1 replicas'
268            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
269
270    def test_two_replica(self):
271        postfix = uuid.uuid4()
272        name = '2replica_{0}'.format(postfix)
273        for serverInfo in self.servers:
274            rest = RestConnection(serverInfo)
275            proxyPort = rest.get_nodes_self().moxi
276            try:
277                rest.create_bucket(bucket=name, ramQuotaMB=200, replicaNumber=2,
278                                   authType='sasl', proxyPort=proxyPort)
279            except BucketCreationException as ex:
280                self.log.error(ex)
281                self.fail('failed to create bucket with 2 replicas')
282
283            msg = 'failed to start up bucket with 2 replicas'
284            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
285
286    def test_three_replica(self):
287        postfix = uuid.uuid4()
288        name = '3replica_{0}'.format(postfix)
289        for serverInfo in self.servers:
290            rest = RestConnection(serverInfo)
291            proxyPort = rest.get_nodes_self().moxi
292            try:
293                rest.create_bucket(bucket=name, ramQuotaMB=200, replicaNumber=3,
294                                   authType='sasl', proxyPort=proxyPort)
295            except BucketCreationException as ex:
296                self.log.error(ex)
297                self.fail('failed to create bucket with 3 replicas')
298
299            msg = 'failed to start up bucket with 3 replicas'
300            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
301
302    def test_four_replica(self):
303        postfix = uuid.uuid4()
304        name = '4replica_{0}'.format(postfix)
305        for serverInfo in self.servers:
306            rest = RestConnection(serverInfo)
307            proxyPort = rest.get_nodes_self().moxi
308            try:
309                rest.create_bucket(bucket=name, ramQuotaMB=200, replicaNumber=4,
310                                   authType='sasl', proxyPort=proxyPort)
311                self.fail('created bucket with 4 replicas')
312            except BucketCreationException as ex:
313                self.log.info(ex)
314
315    # Bucket name can only contain characters in range A-Z, a-z, 0-9 as well as underscore, period, dash & percent. Consult the documentation.
316    def test_valid_chars(self):
317        name = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.%'
318        for serverInfo in self.servers:
319            rest = RestConnection(serverInfo)
320            proxyPort = rest.get_nodes_self().moxi
321            try:
322                rest.create_bucket(bucket=name, ramQuotaMB=200,
323                                   authType='sasl', proxyPort=proxyPort)
324            except BucketCreationException as ex:
325                self.log.error(ex)
326                self.fail('could not create bucket with all valid characters')
327
328            msg = 'failed to start up bucket with all valid characters'
329            self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
330
331    # Bucket name can only contain characters in range A-Z, a-z, 0-9 as well as underscore, period, dash & percent. Consult the documentation.
332    # only done on the first server
333    def test_invalid_chars(self):
334        postfix = uuid.uuid4()
335        for char in ['~', '!', '@', '#', '$', '^', '&', '*', '(', ')', ':', ',', ';', '"', '\'', '<', '>', '?', '/']:
336            name = '{0}invalid_{1}'.format(postfix, char)
337            for serverInfo in [self.servers[0]]:
338                rest = RestConnection(serverInfo)
339                proxyPort = rest.get_nodes_self().moxi
340                try:
341                    rest.create_bucket(bucket=name, ramQuotaMB=200, replicaNumber=2,
342                                       authType='sasl', proxyPort=proxyPort)
343                    self.fail('created a bucket with invalid characters')
344                except BucketCreationException as ex:
345                    self.log.info(ex)
346
347    # create maximum number of buckets (server memory / 100MB)
348    # only done on the first server
349    def test_max_buckets(self):
350        log = logger.Logger.get_logger()
351        serverInfo = self.servers[0]
352        log.info('picking server : {0} as the master'.format(serverInfo))
353        rest = RestConnection(serverInfo)
354        proxyPort = rest.get_nodes_self().moxi
355        info = rest.get_nodes_self()
356        rest.init_cluster(username=serverInfo.rest_username,
357                          password=serverInfo.rest_password)
358        rest.init_cluster_memoryQuota(memoryQuota=info.mcdMemoryReserved)
359        bucket_num = rest.get_internalSettings("maxBucketCount")
360        bucket_ram = 100
361
362        for i in range(bucket_num):
363            bucket_name = 'max_buckets-{0}'.format(uuid.uuid4())
364            rest.create_bucket(bucket=bucket_name,
365                               ramQuotaMB=bucket_ram,
366                               authType='sasl', proxyPort=proxyPort)
367            ready = BucketOperationHelper.wait_for_memcached(serverInfo, bucket_name)
368            self.assertTrue(ready, "wait_for_memcached failed")
369
370        buckets = rest.get_buckets()
371        if len(buckets) != bucket_num:
372            msg = 'tried to create {0} buckets, only created {1}'.format(bucket_count, len(buckets))
373            self.fail(msg)
374        try:
375            rest.create_bucket(bucket=bucket_name,
376                               ramQuotaMB=bucket_ram,
377                               authType='sasl', proxyPort=proxyPort)
378            msg = 'bucket creation did not fail even though system was overcommited'
379            self.fail(msg)
380        except BucketCreationException as ex:
381            self.log.info('BucketCreationException was thrown as expected when we try to create {0} buckets'.
382                          format(bucket_num + 1))
383        buckets = rest.get_buckets()
384        if len(buckets) != bucket_num:
385            msg = 'tried to create {0} buckets, only created {1}'.format(bucket_num + 1, len(buckets))
386            self.fail(msg)
387
388
389    def test_valid_length(self):
390        max_len = 100
391        name_len = self.input.param('name_length', 100)
392        name = 'a' * name_len
393        master = self.servers[0]
394        rest = RestConnection(master)
395        proxyPort = rest.get_nodes_self().moxi
396        try:
397            rest.create_bucket(bucket=name, ramQuotaMB=200,
398                                authType='sasl', proxyPort=proxyPort)
399            if name_len <= max_len:
400                msg = 'failed to start up bucket with valid length'
401                self.assertTrue(BucketOperationHelper.wait_for_bucket_creation(name, rest), msg=msg)
402            else:
403                self.fail('Bucket with invalid length created')
404        except BucketCreationException as ex:
405            self.log.error(ex)
406            if name_len <= max_len:
407                self.fail('could not create bucket with valid length')
408            else:
409                self.log.info('bucket with invalid length not created as expected')
410