~veebers/juju-ci-tools/perf-initial-heatmap-details

« back to all changes in this revision

Viewing changes to assess_storage.py

  • Committer: Curtis Hovey
  • Date: 2016-06-22 22:24:04 UTC
  • mfrom: (1479 trunk)
  • mto: This revision was merged to the branch mainline in revision 1482.
  • Revision ID: curtis@canonical.com-20160622222404-4q35wz64wxci4o6v
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""Assess juju charm storage."""
 
3
 
 
4
from __future__ import print_function
 
5
import os
 
6
 
 
7
import argparse
 
8
import copy
 
9
import json
 
10
import logging
 
11
import sys
 
12
 
 
13
from deploy_stack import (
 
14
    BootstrapManager,
 
15
)
 
16
from jujucharm import Charm
 
17
from utility import (
 
18
    add_basic_testing_arguments,
 
19
    configure_logging,
 
20
    JujuAssertionError,
 
21
    local_charm_path,
 
22
    temp_dir,
 
23
)
 
24
 
 
25
 
 
26
__metaclass__ = type
 
27
 
 
28
 
 
29
log = logging.getLogger("assess_storage")
 
30
 
 
31
 
 
32
storage_pool_details = {
 
33
    "loopy":
 
34
        {
 
35
            "provider": "loop",
 
36
            "attrs":
 
37
                {
 
38
                    "size": "1G"
 
39
                }},
 
40
    "rooty":
 
41
        {
 
42
            "provider": "rootfs",
 
43
            "attrs":
 
44
                {
 
45
                    "size": "1G"
 
46
                }},
 
47
    "tempy":
 
48
        {
 
49
            "provider": "tmpfs",
 
50
            "attrs":
 
51
                {
 
52
                    "size": "1G"
 
53
                }},
 
54
    "ebsy":
 
55
        {
 
56
            "provider": "ebs",
 
57
            "attrs":
 
58
                {
 
59
                    "size": "1G"
 
60
                }}
 
61
}
 
62
 
 
63
storage_pool_1X = copy.deepcopy(storage_pool_details)
 
64
storage_pool_1X["ebs-ssd"] = {
 
65
    "provider": "ebs",
 
66
    "attrs":
 
67
        {
 
68
            "volume-type": "ssd"
 
69
        }
 
70
}
 
71
 
 
72
storage_list_expected = {
 
73
    "storage":
 
74
        {"data/0":
 
75
            {
 
76
                "kind": "filesystem",
 
77
                "attachments":
 
78
                    {
 
79
                        "units":
 
80
                            {
 
81
                                "dummy-storage-fs/0":
 
82
                                    {"location": "/srv/data"}}}}}}
 
83
 
 
84
storage_list_expected_2 = copy.deepcopy(storage_list_expected)
 
85
storage_list_expected_2["storage"]["disks/1"] = {
 
86
    "kind": "block",
 
87
    "attachments":
 
88
        {
 
89
            "units":
 
90
                {"dummy-storage-lp/0":
 
91
                    {
 
92
                        "location": ""}}}}
 
93
storage_list_expected_3 = copy.deepcopy(storage_list_expected_2)
 
94
storage_list_expected_3["storage"]["disks/2"] = {
 
95
    "kind": "block",
 
96
    "attachments":
 
97
        {
 
98
            "units":
 
99
                {"dummy-storage-lp/0":
 
100
                    {
 
101
                        "location": ""}}}}
 
102
storage_list_expected_4 = copy.deepcopy(storage_list_expected_3)
 
103
storage_list_expected_4["storage"]["data/3"] = {
 
104
    "kind": "filesystem",
 
105
    "attachments":
 
106
        {
 
107
            "units":
 
108
                {"dummy-storage-tp/0":
 
109
                    {
 
110
                        "location": "/srv/data"}}}}
 
111
storage_list_expected_5 = copy.deepcopy(storage_list_expected_4)
 
112
storage_list_expected_5["storage"]["data/4"] = {
 
113
    "kind": "filesystem",
 
114
    "attachments":
 
115
        {
 
116
            "units":
 
117
                {"dummy-storage-np/0":
 
118
                    {
 
119
                        "location": "/srv/data"}}}}
 
120
storage_list_expected_6 = copy.deepcopy(storage_list_expected_5)
 
121
storage_list_expected_6["storage"]["data/5"] = {
 
122
    "kind": "filesystem",
 
123
    "attachments":
 
124
        {
 
125
            "units":
 
126
                {"dummy-storage-mp/0":
 
127
                    {
 
128
                        "location": "/srv/data"}}}}
 
129
 
 
130
 
 
131
def storage_list(client):
 
132
    """Return the storage list."""
 
133
    list_storage = json.loads(client.list_storage())
 
134
    for instance in list_storage["storage"].keys():
 
135
        try:
 
136
            list_storage["storage"][instance].pop("status")
 
137
            list_storage["storage"][instance].pop("persistent")
 
138
            attachments = list_storage["storage"][instance]["attachments"]
 
139
            unit = attachments["units"].keys()[0]
 
140
            attachments["units"][unit].pop("machine")
 
141
            if instance.startswith("disks"):
 
142
                attachments["units"][unit]["location"] = ""
 
143
        except Exception:
 
144
            pass
 
145
    return list_storage
 
146
 
 
147
 
 
148
def storage_pool_list(client):
 
149
    """Return the list of storage pool."""
 
150
    return json.loads(client.list_storage_pool())
 
151
 
 
152
 
 
153
def create_storage_charm(charm_dir, name, summary, storage):
 
154
    """Manually create a temporary charm to test with storage."""
 
155
    storage_charm = Charm(name, summary, storage=storage, series=['trusty'])
 
156
    charm_root = storage_charm.to_repo_dir(charm_dir)
 
157
    return charm_root
 
158
 
 
159
 
 
160
def assess_create_pool(client):
 
161
    """Test creating storage pool."""
 
162
    for name, pool in storage_pool_details.iteritems():
 
163
        client.create_storage_pool(name, pool["provider"],
 
164
                                   pool["attrs"]["size"])
 
165
 
 
166
 
 
167
def assess_add_storage(client, unit, storage_type, amount="1"):
 
168
    """Test adding storage instances to service.
 
169
 
 
170
    Only type 'disk' is able to add instances.
 
171
    """
 
172
    client.add_storage(unit, storage_type, amount)
 
173
 
 
174
 
 
175
def deploy_storage(client, charm, series, pool, amount="1G", charm_repo=None):
 
176
    """Test deploying charm with storage."""
 
177
    if pool == "loop":
 
178
        client.deploy(charm, series=series, repository=charm_repo,
 
179
                      storage="disks=" + pool + "," + amount)
 
180
    elif pool is None:
 
181
        client.deploy(charm, series=series, repository=charm_repo,
 
182
                      storage="data=" + amount)
 
183
    else:
 
184
        client.deploy(charm, series=series, repository=charm_repo,
 
185
                      storage="data=" + pool + "," + amount)
 
186
    client.wait_for_started()
 
187
 
 
188
 
 
189
def assess_deploy_storage(client, charm_series,
 
190
                          charm_name, provider_type, pool=None):
 
191
    """Set up the test for deploying charm with storage."""
 
192
    if provider_type == "block":
 
193
        storage = {
 
194
            "disks": {
 
195
                "type": provider_type,
 
196
                "multiple": {
 
197
                    "range": "0-10"
 
198
                }
 
199
            }
 
200
        }
 
201
    else:
 
202
        storage = {
 
203
            "data": {
 
204
                "type": provider_type,
 
205
                "location": "/srv/data"
 
206
            }
 
207
        }
 
208
    with temp_dir() as charm_dir:
 
209
        charm_root = create_storage_charm(charm_dir, charm_name,
 
210
                                          'Test charm for storage', storage)
 
211
        platform = 'ubuntu'
 
212
        charm = local_charm_path(charm=charm_name, juju_ver=client.version,
 
213
                                 series=charm_series,
 
214
                                 repository=os.path.dirname(charm_root),
 
215
                                 platform=platform)
 
216
        deploy_storage(client, charm, charm_series, pool, "1G", charm_dir)
 
217
 
 
218
 
 
219
def assess_multiple_provider(client, charm_series, amount, charm_name,
 
220
                             provider_1, provider_2, pool_1, pool_2):
 
221
    storage = {}
 
222
    for provider in [provider_1, provider_2]:
 
223
        if provider == "block":
 
224
            storage.update({
 
225
                "disks": {
 
226
                    "type": provider,
 
227
                    "multiple": {
 
228
                        "range": "0-10"
 
229
                    }
 
230
                }
 
231
            })
 
232
        else:
 
233
            storage.update({
 
234
                "data": {
 
235
                    "type": provider,
 
236
                    "location": "/srv/data"
 
237
                }
 
238
            })
 
239
    with temp_dir() as charm_dir:
 
240
        charm_root = create_storage_charm(charm_dir, charm_name,
 
241
                                          'Test charm for storage', storage)
 
242
        platform = 'ubuntu'
 
243
        charm = local_charm_path(charm=charm_name, juju_ver=client.version,
 
244
                                 series=charm_series,
 
245
                                 repository=os.path.dirname(charm_root),
 
246
                                 platform=platform)
 
247
        if pool_1 == "loop":
 
248
            command = "disks=" + pool_1 + "," + amount
 
249
        else:
 
250
            command = "data=" + pool_1 + "," + amount
 
251
        if pool_2 == "loop":
 
252
            command = command + ",disks=" + pool_2
 
253
        else:
 
254
            command = command + ",data=" + pool_2
 
255
        client.deploy(charm, series=charm_series, repository=charm_dir,
 
256
                      storage=command)
 
257
        client.wait_for_started()
 
258
 
 
259
 
 
260
def assess_storage(client, charm_series):
 
261
    """Test the storage feature."""
 
262
    assess_create_pool(client)
 
263
    pool_list = storage_pool_list(client)
 
264
    if client.version.startswith('2.'):
 
265
        if pool_list != storage_pool_details:
 
266
            raise JujuAssertionError(pool_list)
 
267
    elif client.version.startswith('1.'):
 
268
        if pool_list != storage_pool_1X:
 
269
            raise JujuAssertionError(pool_list)
 
270
    assess_deploy_storage(client, charm_series,
 
271
                          'dummy-storage-fs', 'filesystem', 'rootfs')
 
272
    storage_list_derived = storage_list(client)
 
273
    if storage_list_derived != storage_list_expected:
 
274
        raise JujuAssertionError(storage_list_derived)
 
275
    assess_deploy_storage(client, charm_series,
 
276
                          'dummy-storage-lp', 'block', 'loop')
 
277
    storage_list_derived = storage_list(client)
 
278
    if storage_list_derived != storage_list_expected_2:
 
279
        raise JujuAssertionError(storage_list_derived)
 
280
    assess_add_storage(client, 'dummy-storage-lp/0', 'disks', "1")
 
281
    storage_list_derived = storage_list(client)
 
282
    if storage_list_derived != storage_list_expected_3:
 
283
        raise JujuAssertionError(storage_list_derived)
 
284
    assess_deploy_storage(client, charm_series,
 
285
                          'dummy-storage-tp', 'filesystem', 'tmpfs')
 
286
    storage_list_derived = storage_list(client)
 
287
    if storage_list_derived != storage_list_expected_4:
 
288
        raise JujuAssertionError(storage_list_derived)
 
289
    assess_deploy_storage(client, charm_series,
 
290
                          'dummy-storage-np', 'filesystem')
 
291
    storage_list_derived = storage_list(client)
 
292
    if storage_list_derived != storage_list_expected_5:
 
293
        raise JujuAssertionError(storage_list_derived)
 
294
    assess_multiple_provider(client, charm_series, "1G", 'dummy-storage-mp',
 
295
                             'filesystem', 'block', 'rootfs', 'loop')
 
296
    storage_list_derived = storage_list(client)
 
297
    if storage_list_derived != storage_list_expected_6:
 
298
        raise JujuAssertionError(storage_list_derived)
 
299
    # storage with provider 'ebs' is only available under 'aws'
 
300
    # assess_deploy_storage(client, charm_series,
 
301
    #                       'dummy-storage-eb', 'filesystem', 'ebs')
 
302
 
 
303
 
 
304
def parse_args(argv):
 
305
    """Parse all arguments."""
 
306
    parser = argparse.ArgumentParser(description="Test Storage Feature")
 
307
    add_basic_testing_arguments(parser)
 
308
    parser.set_defaults(series='trusty')
 
309
    return parser.parse_args(argv)
 
310
 
 
311
 
 
312
def main(argv=None):
 
313
    args = parse_args(argv)
 
314
    configure_logging(args.verbose)
 
315
    bs_manager = BootstrapManager.from_args(args)
 
316
    with bs_manager.booted_context(args.upload_tools):
 
317
        assess_storage(bs_manager.client, bs_manager.series)
 
318
    return 0
 
319
 
 
320
 
 
321
if __name__ == '__main__':
 
322
    sys.exit(main())