forked from redhat-openstack/packstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathswift_600.py
More file actions
326 lines (279 loc) · 11.5 KB
/
Copy pathswift_600.py
File metadata and controls
326 lines (279 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Installs and configures Swift
"""
import re
import uuid
import netaddr
from packstack.installer import basedefs
from packstack.installer import validators
from packstack.installer import processors
from packstack.installer.exceptions import ParamValidationError
from packstack.installer import utils
from packstack.installer.utils import split_hosts
from packstack.modules.documentation import update_params_usage
# ------------- Swift Packstack Plugin Initialization --------------
PLUGIN_NAME = "OS-Swift"
PLUGIN_NAME_COLORED = utils.color_text(PLUGIN_NAME, 'blue')
def initConfig(controller):
params = [
{"CMD_OPTION": "os-swift-ks-passwd",
"PROMPT": "Enter the password for the Swift Keystone access",
"OPTION_LIST": [],
"VALIDATORS": [validators.validate_not_empty],
"DEFAULT_VALUE": "PW_PLACEHOLDER",
"PROCESSORS": [processors.process_password],
"MASK_INPUT": True,
"LOOSE_VALIDATION": False,
"CONF_NAME": "CONFIG_SWIFT_KS_PW",
"USE_DEFAULT": False,
"NEED_CONFIRM": True,
"CONDITION": False},
{"CMD_OPTION": "os-swift-storages",
"PROMPT": "Enter the Swift Storage devices e.g. /path/to/dev",
"OPTION_LIST": [],
"VALIDATORS": [validate_storage],
"DEFAULT_VALUE": '',
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_SWIFT_STORAGES",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False,
"DEPRECATES": ['CONFIG_SWIFT_STORAGE_HOSTS']},
{"CMD_OPTION": "os-swift-storage-zones",
"PROMPT": ("Enter the number of swift storage zones, MUST be no "
"bigger than the number of storage devices configured"),
"OPTION_LIST": [],
"VALIDATORS": [validators.validate_integer],
"DEFAULT_VALUE": "1",
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_SWIFT_STORAGE_ZONES",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False},
{"CMD_OPTION": "os-swift-storage-replicas",
"PROMPT": ("Enter the number of swift storage replicas, MUST be no "
"bigger than the number of storage zones configured"),
"OPTION_LIST": [],
"VALIDATORS": [validators.validate_integer],
"DEFAULT_VALUE": "1",
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_SWIFT_STORAGE_REPLICAS",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False},
{"CMD_OPTION": "os-swift-storage-fstype",
"PROMPT": "Enter FileSystem type for storage nodes",
"OPTION_LIST": ['xfs', 'ext4'],
"VALIDATORS": [validators.validate_options],
"DEFAULT_VALUE": "ext4",
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_SWIFT_STORAGE_FSTYPE",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False},
{"CMD_OPTION": "os-swift-hash",
"PROMPT": "Enter hash for Swift shared secret",
"OPTION_LIST": [],
"VALIDATORS": [validators.validate_not_empty],
"DEFAULT_VALUE": uuid.uuid4().hex[:16],
"MASK_INPUT": True,
"LOOSE_VALIDATION": False,
"CONF_NAME": "CONFIG_SWIFT_HASH",
"USE_DEFAULT": True,
"NEED_CONFIRM": True,
"CONDITION": False},
{"CMD_OPTION": "os-swift-storage-size",
"PROMPT": ("Enter the size of the storage device (eg. 2G, 2000M, "
"2000000K)"),
"OPTION_LIST": [],
"VALIDATORS": [validate_storage_size],
"DEFAULT_VALUE": "2G",
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_SWIFT_STORAGE_SIZE",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False},
]
update_params_usage(basedefs.PACKSTACK_DOC, params, sectioned=False)
group = {"GROUP_NAME": "OSSWIFT",
"DESCRIPTION": "OpenStack Swift Config parameters",
"PRE_CONDITION": "CONFIG_SWIFT_INSTALL",
"PRE_CONDITION_MATCH": "y",
"POST_CONDITION": False,
"POST_CONDITION_MATCH": True}
controller.addGroup(group, params)
def initSequences(controller):
if controller.CONF['CONFIG_SWIFT_INSTALL'] != 'y':
return
steps = [
{'title': 'Preparing Swift builder entries',
'functions': [create_builder_manifest]},
{'title': 'Preparing Swift proxy entries',
'functions': [create_proxy_manifest]},
{'title': 'Preparing Swift storage entries',
'functions': [create_storage_manifest]},
]
controller.addSequence("Installing OpenStack Swift", [], [], steps)
# ------------------------- helper functions -------------------------
def validate_storage(param, options=None):
if not param:
return
if not param.startswith('/'):
raise ParamValidationError(
'Storage value has to be in format "/path/to/device".'
)
def validate_storage_size(param, options=None):
match = re.match(r'\d+G|\d+M|\d+K', param, re.IGNORECASE)
if not match:
msg = 'Storage size not have a valid value (eg. 1G, 1000M, 1000000K)'
raise ParamValidationError(msg)
def parse_devices(config):
"""
Returns dict containing information about Swift storage devices.
"""
devices = []
device_number = 0
num_zones = int(config["CONFIG_SWIFT_STORAGE_ZONES"])
for device in config["CONFIG_SWIFT_STORAGES"].split(","):
# we have to get rid of host part in case deprecated parameter
# CONFIG_SWIFT_STORAGE_HOSTS has been used
if ':' in device:
device = device.split(':')[1]
# device should be empty string in case only IP address has been used
try:
netaddr.IPAddress(device)
except Exception:
device = device.strip()
else:
device = ''
if not device:
continue
device_number += 1
zone = str((device_number % num_zones) + 1)
devices.append({'device': device, 'zone': zone,
'device_name': 'device%s' % device_number})
if not devices:
devices.append({'device': None, 'zone': 1,
'device_name': 'swiftloopback'})
config['CONFIG_SWIFT_LOOPBACK'] = 'y'
else:
config['CONFIG_SWIFT_LOOPBACK'] = 'n'
return devices
def check_device(host, device):
"""
Raises ScriptRuntimeError if given device is not mounted on given
host.
"""
server = utils.ScriptRunner(host)
# the device MUST exist
cmd = 'ls -l %s'
server.append(cmd % device)
# if it is not mounted then we can use it
cmd = 'grep "%s " /proc/self/mounts || exit 0'
server.append(cmd % device)
# if it is mounted then the mount point has to be in /srv/node
cmd = 'grep "%s /srv/node" /proc/self/mounts && exit 0'
server.append(cmd % device)
# if we got here without exiting then we can't use this device
server.append('exit 1')
server.execute()
def get_storage_size(config):
ranges = {'G': 1048576, 'M': 1024, 'K': 1}
size = config['CONFIG_SWIFT_STORAGE_SIZE'].strip()
for measure in ['G', 'M', 'K']:
if re.match('\d+' + measure, size, re.IGNORECASE):
intsize = int(size.rstrip(measure)) * ranges[measure]
return intsize
# -------------------------- step functions --------------------------
def create_builder_manifest(config, messages):
global devices
devices = parse_devices(config)
# The ring file should be built and distributed before the storage services
# come up. Specifically the replicator crashes if the ring isn't present
def device_def(dev_type, host, dev_port, devicename, zone):
# device host has to be IP address
host = utils.force_ip(host)
fmt = ('\n@@%s { "%s:%s/%s":\n'
' zone => %s,\n'
' weight => 10, }\n')
return fmt % (dev_type, host, dev_port, devicename, zone)
# Add each device to the ring
devicename = 0
for configkey, dev_type, dev_port in (
[('SWIFT_RING_OBJECT_DEVICES', 'ring_object_device', 6000),
('SWIFT_RING_CONTAINER_DEVICES', 'ring_container_device', 6001),
('SWIFT_RING_ACCOUNT_DEVICES', 'ring_account_device', 6002)]):
swift_dev_details = dict()
host = utils.force_ip(config['CONFIG_STORAGE_HOST_URL'])
fstype = config["CONFIG_SWIFT_STORAGE_FSTYPE"]
for device in devices:
devicename = device['device_name']
key = "dev_%s_%s" % (host, devicename)
swift_dev_details.setdefault(key, {})
zone = device['zone']
swift_dev_details[key]['name'] = "%s:%s/%s" % (host, dev_port,
devicename)
swift_dev_details[key]['weight'] = "%s" % 10
swift_dev_details[key]['zone'] = "%s" % zone
config[configkey] = swift_dev_details
def create_proxy_manifest(config, messages):
fw_details = dict()
key = "swift_proxy"
fw_details.setdefault(key, {})
fw_details[key]['host'] = "ALL"
fw_details[key]['service_name'] = "swift proxy"
fw_details[key]['chain'] = "INPUT"
fw_details[key]['ports'] = ['8080']
fw_details[key]['proto'] = "tcp"
config['FIREWALL_SWIFT_PROXY_RULES'] = fw_details
def create_storage_manifest(config, messages):
global devices
devicename = 0
swift_dev_details = dict()
host = utils.force_ip(config['CONFIG_STORAGE_HOST_URL'])
fstype = config["CONFIG_SWIFT_STORAGE_FSTYPE"]
# this need to happen once per storage device
for device in devices:
if device['device'] is None:
config['CONFIG_SWIFT_STORAGE_SEEK'] = get_storage_size(config)
else:
devicename = device['device_name']
devicedev = device['device']
key = "dev_%s_%s" % (host, devicename)
swift_dev_details.setdefault(key, {})
swift_dev_details[key]['device'] = "%s" % devicename
swift_dev_details[key]['dev'] = "%s" % devicedev
swift_dev_details[key]['fstype'] = "%s" % fstype
config['CONFIG_SWIFT_STORAGE_DEVICES'] = swift_dev_details
# set allowed hosts for firewall
hosts = set([config['CONFIG_STORAGE_HOST']])
if config['CONFIG_NOVA_INSTALL'] == 'y':
hosts |= split_hosts(config['CONFIG_COMPUTE_HOSTS'])
fw_details = dict()
for host in hosts:
key = "swift_storage_and_rsync_%s" % host
fw_details.setdefault(key, {})
fw_details[key]['host'] = "%s" % host
fw_details[key]['service_name'] = "swift storage and rsync"
fw_details[key]['chain'] = "INPUT"
fw_details[key]['ports'] = ['6000', '6001', '6002', '873']
fw_details[key]['proto'] = "tcp"
config['FIREWALL_SWIFT_STORAGE_RULES'] = fw_details