~devstack-core/devstack/github

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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
#!/bin/bash
#
# functions - DevStack-specific functions
#
# The following variables are assumed to be defined by certain functions:
#
# - ``DATABASE_BACKENDS``
# - ``ENABLED_SERVICES``
# - ``FILES``
# - ``GLANCE_HOSTPORT``
#

# Include the common functions
FUNC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
source ${FUNC_DIR}/functions-common
source ${FUNC_DIR}/inc/ini-config
source ${FUNC_DIR}/inc/python
source ${FUNC_DIR}/inc/rootwrap

# Save trace setting
XTRACE=$(set +o | grep xtrace)
set +o xtrace

# Check if a function already exists
function function_exists {
    declare -f -F $1 > /dev/null
}

# Retrieve an image from a URL and upload into Glance.
# Uses the following variables:
#
# - ``FILES`` must be set to the cache dir
# - ``GLANCE_HOSTPORT``
#
# upload_image image-url glance-token
function upload_image {
    local image_url=$1
    local token=$2

    local image image_fname image_name

    # Create a directory for the downloaded image tarballs.
    mkdir -p $FILES/images
    image_fname=`basename "$image_url"`
    if [[ $image_url != file* ]]; then
        # Downloads the image (uec ami+akistyle), then extracts it.
        if [[ ! -f $FILES/$image_fname || "$(stat -c "%s" $FILES/$image_fname)" = "0" ]]; then
            wget --progress=dot:giga -c $image_url -O $FILES/$image_fname
            if [[ $? -ne 0 ]]; then
                echo "Not found: $image_url"
                return
            fi
        fi
        image="$FILES/${image_fname}"
    else
        # File based URL (RFC 1738): ``file://host/path``
        # Remote files are not considered here.
        # unix: ``file:///home/user/path/file``
        # windows: ``file:///C:/Documents%20and%20Settings/user/path/file``
        image=$(echo $image_url | sed "s/^file:\/\///g")
        if [[ ! -f $image || "$(stat -c "%s" $image)" == "0" ]]; then
            echo "Not found: $image_url"
            return
        fi
    fi

    # OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading
    if [[ "$image_url" =~ 'openvz' ]]; then
        image_name="${image_fname%.tar.gz}"
        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format ami --disk-format ami < "${image}"
        return
    fi

    # vmdk format images
    if [[ "$image_url" =~ '.vmdk' ]]; then
        image_name="${image_fname%.vmdk}"

        # Before we can upload vmdk type images to glance, we need to know it's
        # disk type, storage adapter, and networking adapter. These values are
        # passed to glance as custom properties.
        # We take these values from the vmdk file if populated. Otherwise, we use
        # vmdk filename, which is expected in the following format:
        #
        #     <name>-<disk type>;<storage adapter>;<network adapter>
        #
        # If the filename does not follow the above format then the vsphere
        # driver will supply default values.

        local vmdk_disktype=""
        local vmdk_net_adapter="e1000"
        local path_len

        # vmdk adapter type
        local vmdk_adapter_type="$(head -25 $image | { grep -a -F -m 1 'ddb.adapterType =' $image || true; })"
        vmdk_adapter_type="${vmdk_adapter_type#*\"}"
        vmdk_adapter_type="${vmdk_adapter_type%?}"

        # vmdk disk type
        local vmdk_create_type="$(head -25 $image | { grep -a -F -m 1 'createType=' $image || true; })"
        vmdk_create_type="${vmdk_create_type#*\"}"
        vmdk_create_type="${vmdk_create_type%\"*}"

        descriptor_data_pair_msg="Monolithic flat and VMFS disks "`
                                    `"should use a descriptor-data pair."
        if [[ "$vmdk_create_type" = "monolithicSparse" ]]; then
            vmdk_disktype="sparse"
        elif [[ "$vmdk_create_type" = "monolithicFlat" || "$vmdk_create_type" = "vmfs" ]]; then
            # Attempt to retrieve the ``*-flat.vmdk``
            local flat_fname="$(head -25 $image | { grep -G 'RW\|RDONLY [0-9]+ FLAT\|VMFS' $image || true; })"
            flat_fname="${flat_fname#*\"}"
            flat_fname="${flat_fname%?}"
            if [[ -z "$flat_fname" ]]; then
                flat_fname="$image_name-flat.vmdk"
            fi
            path_len=`expr ${#image_url} - ${#image_fname}`
            local flat_url="${image_url:0:$path_len}$flat_fname"
            warn $LINENO "$descriptor_data_pair_msg"`
                            `" Attempt to retrieve the *-flat.vmdk: $flat_url"
            if [[ $flat_url != file* ]]; then
                if [[ ! -f $FILES/$flat_fname || \
                "$(stat -c "%s" $FILES/$flat_fname)" = "0" ]]; then
                    wget --progress=dot:giga -c $flat_url -O $FILES/$flat_fname
                fi
                image="$FILES/${flat_fname}"
            else
                image=$(echo $flat_url | sed "s/^file:\/\///g")
                if [[ ! -f $image || "$(stat -c "%s" $image)" == "0" ]]; then
                    echo "Flat disk not found: $flat_url"
                    return 1
                fi
            fi
            image_name="${flat_fname}"
            vmdk_disktype="preallocated"
        elif [[ "$vmdk_create_type" = "streamOptimized" ]]; then
            vmdk_disktype="streamOptimized"
        elif [[ -z "$vmdk_create_type" ]]; then
            # *-flat.vmdk provided: attempt to retrieve the descriptor (*.vmdk)
            # to retrieve appropriate metadata
            if [[ ${image_name: -5} != "-flat" ]]; then
                warn $LINENO "Expected filename suffix: '-flat'."`
                            `" Filename provided: ${image_name}"
            else
                descriptor_fname="${image_name:0:${#image_name} - 5}.vmdk"
                path_len=`expr ${#image_url} - ${#image_fname}`
                local flat_path="${image_url:0:$path_len}"
                local descriptor_url=$flat_path$descriptor_fname
                warn $LINENO "$descriptor_data_pair_msg"`
                                `" Attempt to retrieve the descriptor *.vmdk: $descriptor_url"
                if [[ $flat_path != file* ]]; then
                    if [[ ! -f $FILES/$descriptor_fname || \
                    "$(stat -c "%s" $FILES/$descriptor_fname)" = "0" ]]; then
                        wget -c $descriptor_url -O $FILES/$descriptor_fname
                    fi
                    descriptor_url="$FILES/$descriptor_fname"
                else
                    descriptor_url=$(echo $descriptor_url | sed "s/^file:\/\///g")
                    if [[ ! -f $descriptor_url || \
                    "$(stat -c "%s" $descriptor_url)" == "0" ]]; then
                        echo "Descriptor not found: $descriptor_url"
                        return 1
                    fi
                fi
                vmdk_adapter_type="$(head -25 $descriptor_url | { grep -a -F -m 1 'ddb.adapterType =' $descriptor_url || true; })"
                vmdk_adapter_type="${vmdk_adapter_type#*\"}"
                vmdk_adapter_type="${vmdk_adapter_type%?}"
            fi
            vmdk_disktype="preallocated"
        else
            vmdk_disktype="preallocated"
        fi

        # NOTE: For backwards compatibility reasons, colons may be used in place
        # of semi-colons for property delimiters but they are not permitted
        # characters in NTFS filesystems.
        property_string=`echo "$image_name" | { grep -oP '(?<=-)(?!.*-).*[:;].*[:;].*$' || true; }`
        IFS=':;' read -a props <<< "$property_string"
        vmdk_disktype="${props[0]:-$vmdk_disktype}"
        vmdk_adapter_type="${props[1]:-$vmdk_adapter_type}"
        vmdk_net_adapter="${props[2]:-$vmdk_net_adapter}"

        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}"
        return
    fi

    # XenServer-vhd-ovf-format images are provided as .vhd.tgz
    # and should not be decompressed prior to loading
    if [[ "$image_url" =~ '.vhd.tgz' ]]; then
        image_name="${image_fname%.vhd.tgz}"
        local force_vm_mode=""
        if [[ "$image_name" =~ 'cirros' ]]; then
            # Cirros VHD image currently only boots in PV mode.
            # Nova defaults to PV for all VHD images, but
            # the glance setting is needed for booting
            # directly from volume.
            force_vm_mode="--property vm_mode=xen"
        fi
        openstack \
            --os-token $token \
            --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
            image create \
            "$image_name" --public \
            --container-format=ovf --disk-format=vhd \
            $force_vm_mode < "${image}"
        return
    fi

    # .xen-raw.tgz suggests a Xen capable raw image inside a tgz.
    # and should not be decompressed prior to loading.
    # Setting metadata, so PV mode is used.
    if [[ "$image_url" =~ '.xen-raw.tgz' ]]; then
        image_name="${image_fname%.xen-raw.tgz}"
        openstack \
            --os-token $token \
            --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
            image create \
            "$image_name" --public \
            --container-format=tgz --disk-format=raw \
            --property vm_mode=xen < "${image}"
        return
    fi

    local kernel=""
    local ramdisk=""
    local disk_format=""
    local container_format=""
    local unpack=""
    local img_property=""
    case "$image_fname" in
        *.tar.gz|*.tgz)
            # Extract ami and aki files
            [ "${image_fname%.tar.gz}" != "$image_fname" ] &&
                image_name="${image_fname%.tar.gz}" ||
                image_name="${image_fname%.tgz}"
            local xdir="$FILES/images/$image_name"
            rm -Rf "$xdir";
            mkdir "$xdir"
            tar -zxf $image -C "$xdir"
            kernel=$(for f in "$xdir/"*-vmlinuz* "$xdir/"aki-*/image; do
                [ -f "$f" ] && echo "$f" && break; done; true)
            ramdisk=$(for f in "$xdir/"*-initrd* "$xdir/"ari-*/image; do
                [ -f "$f" ] && echo "$f" && break; done; true)
            image=$(for f in "$xdir/"*.img "$xdir/"ami-*/image; do
                [ -f "$f" ] && echo "$f" && break; done; true)
            if [[ -z "$image_name" ]]; then
                image_name=$(basename "$image" ".img")
            fi
            ;;
        *.img)
            image_name=$(basename "$image" ".img")
            local format=$(qemu-img info ${image} | awk '/^file format/ { print $3; exit }')
            if [[ ",qcow2,raw,vdi,vmdk,vpc," =~ ",$format," ]]; then
                disk_format=$format
            else
                disk_format=raw
            fi
            container_format=bare
            ;;
        *.img.gz)
            image_name=$(basename "$image" ".img.gz")
            disk_format=raw
            container_format=bare
            unpack=zcat
            ;;
        *.qcow2)
            image_name=$(basename "$image" ".qcow2")
            disk_format=qcow2
            container_format=bare
            ;;
        *.iso)
            image_name=$(basename "$image" ".iso")
            disk_format=iso
            container_format=bare
            ;;
        *.vhd|*.vhdx|*.vhd.gz|*.vhdx.gz)
            local extension="${image_fname#*.}"
            image_name=$(basename "$image" ".$extension")
            disk_format=vhd
            container_format=bare
            if [ "${image_fname##*.}" == "gz" ]; then
                unpack=zcat
            fi
            ;;
        *) echo "Do not know what to do with $image_fname"; false;;
    esac

    if is_arch "ppc64"; then
        img_property="--property hw_cdrom_bus=scsi"
    fi

    if is_arch "aarch64"; then
        img_property="--property hw_machine_type=virt --property hw_cdrom_bus=virtio --property os_command_line='console=ttyAMA0'"
    fi

    if [ "$container_format" = "bare" ]; then
        if [ "$unpack" = "zcat" ]; then
            openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}")
        else
            openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}"
        fi
    else
        # Use glance client to add the kernel the root filesystem.
        # We parse the results of the first upload to get the glance ID of the
        # kernel for use when uploading the root filesystem.
        local kernel_id="" ramdisk_id="";
        if [ -n "$kernel" ]; then
            kernel_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2)
        fi
        if [ -n "$ramdisk" ]; then
            ramdisk_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2)
        fi
        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}"
    fi
}


# Set the database backend to use
# When called from stackrc/localrc DATABASE_BACKENDS has not been
# initialized yet, just save the configuration selection and call back later
# to validate it.
#
# ``$1`` - the name of the database backend to use (mysql, postgresql, ...)
function use_database {
    if [[ -z "$DATABASE_BACKENDS" ]]; then
        # No backends registered means this is likely called from ``localrc``
        # This is now deprecated usage
        DATABASE_TYPE=$1
        DEPRECATED_TEXT="$DEPRECATED_TEXT\nThe database backend needs to be properly set in ENABLED_SERVICES; use_database is deprecated localrc\n"
    else
        # This should no longer get called...here for posterity
        use_exclusive_service DATABASE_BACKENDS DATABASE_TYPE $1
    fi
}

#Macro for curl statements. curl requires -g option for literal IPv6 addresses.
CURL_GET="${CURL_GET:-curl -g}"

# Wait for an HTTP server to start answering requests
# wait_for_service timeout url
function wait_for_service {
    local timeout=$1
    local url=$2
    timeout $timeout sh -c "while ! $CURL_GET -k --noproxy '*' -s $url >/dev/null; do sleep 1; done"
}


# ping check
# Uses globals ``ENABLED_SERVICES``, ``TOP_DIR``, ``MULTI_HOST``, ``PRIVATE_NETWORK``
# ping_check <ip> [boot-timeout] [from_net] [expected]
function ping_check {
    local ip=$1
    local timeout=${2:-30}
    local from_net=${3:-""}
    local expected=${4:-True}
    local op="!"
    local failmsg="[Fail] Couldn't ping server"
    local ping_cmd="ping"

    # if we don't specify a from_net we're expecting things to work
    # fine from our local box.
    if [[ -n "$from_net" ]]; then
        if is_service_enabled neutron; then
            ping_cmd="$TOP_DIR/tools/ping_neutron.sh $from_net"
        elif [[ "$MULTI_HOST" = "True" && "$from_net" = "$PRIVATE_NETWORK_NAME" ]]; then
            # there is no way to address the multihost / private case, bail here for compatibility.
            # TODO: remove this cruft and redo code to handle this at the caller level.
            return
        fi
    fi

    # inverse the logic if we're testing no connectivity
    if [[ "$expected" != "True" ]]; then
        op=""
        failmsg="[Fail] Could ping server"
    fi

    # Because we've transformed this command so many times, print it
    # out at the end.
    local check_command="while $op $ping_cmd -c1 -w1 $ip; do sleep 1; done"
    echo "Checking connectivity with $check_command"

    if ! timeout $timeout sh -c "$check_command"; then
        die $LINENO $failmsg
    fi
}

# Get ip of instance
function get_instance_ip {
    local vm_id=$1
    local network_name=$2
    local nova_result="$(nova show $vm_id)"
    local ip=$(echo "$nova_result" | grep "$network_name" | get_field 2)
    if [[ $ip = "" ]];then
        echo "$nova_result"
        die $LINENO "[Fail] Coudn't get ipaddress of VM"
    fi
    echo $ip
}

# ssh check

# ssh_check net-name key-file floating-ip default-user active-timeout
function ssh_check {
    if is_service_enabled neutron; then
        _ssh_check_neutron  "$1" $2 $3 $4 $5
        return
    fi
    _ssh_check_novanet "$1" $2 $3 $4 $5
}

function _ssh_check_novanet {
    local NET_NAME=$1
    local KEY_FILE=$2
    local FLOATING_IP=$3
    local DEFAULT_INSTANCE_USER=$4
    local ACTIVE_TIMEOUT=$5
    local probe_cmd=""
    if ! timeout $ACTIVE_TIMEOUT sh -c "while ! ssh -o StrictHostKeyChecking=no -i $KEY_FILE ${DEFAULT_INSTANCE_USER}@$FLOATING_IP echo success; do sleep 1; done"; then
        die $LINENO "server didn't become ssh-able!"
    fi
}


# Get the location of the $module-rootwrap executables, where module is cinder
# or nova.
# get_rootwrap_location module
function get_rootwrap_location {
    local module=$1

    echo "$(get_python_exec_prefix)/$module-rootwrap"
}


# Path permissions sanity check
# check_path_perm_sanity path
function check_path_perm_sanity {
    # Ensure no element of the path has 0700 permissions, which is very
    # likely to cause issues for daemons.  Inspired by default 0700
    # homedir permissions on RHEL and common practice of making DEST in
    # the stack user's homedir.

    local real_path=$(readlink -f $1)
    local rebuilt_path=""
    for i in $(echo ${real_path} | tr "/" " "); do
        rebuilt_path=$rebuilt_path"/"$i

        if [[ $(stat -c '%a' ${rebuilt_path}) = 700 ]]; then
            echo "*** DEST path element"
            echo "***    ${rebuilt_path}"
            echo "*** appears to have 0700 permissions."
            echo "*** This is very likely to cause fatal issues for DevStack daemons."

            if [[ -n "$SKIP_PATH_SANITY" ]]; then
                return
            else
                echo "*** Set SKIP_PATH_SANITY to skip this check"
                die $LINENO "Invalid path permissions"
            fi
        fi
    done
}


# This function recursively compares versions, and is not meant to be
# called by anything other than vercmp_numbers below. This function does
# not work with alphabetic versions.
#
# _vercmp_r sep ver1 ver2
function _vercmp_r {
    typeset sep
    typeset -a ver1=() ver2=()
    sep=$1; shift
    ver1=("${@:1:sep}")
    ver2=("${@:sep+1}")

    if ((ver1 > ver2)); then
        echo 1; return 0
    elif ((ver2 > ver1)); then
        echo -1; return 0
    fi

    if ((sep <= 1)); then
        echo 0; return 0
    fi

    _vercmp_r $((sep-1)) "${ver1[@]:1}" "${ver2[@]:1}"
}


# This function compares two versions and is meant to be called by
# external callers. Please note the function assumes non-alphabetic
# versions. For example, this will work:
#
#   vercmp_numbers 1.10 1.4
#
# The above will return "1", as 1.10 is greater than 1.4.
#
#   vercmp_numbers 5.2 6.4
#
# The above will return "-1", as 5.2 is less than 6.4.
#
#   vercmp_numbers 4.0 4.0
#
# The above will return "0", as the versions are equal.
#
# vercmp_numbers ver1 ver2
function vercmp_numbers {
    typeset v1=$1 v2=$2 sep
    typeset -a ver1 ver2

    IFS=. read -ra ver1 <<< "$v1"
    IFS=. read -ra ver2 <<< "$v2"

    _vercmp_r "${#ver1[@]}" "${ver1[@]}" "${ver2[@]}"
}


# This function sets log formatting options for colorizing log
# output to stdout. It is meant to be called by lib modules.
# The last two parameters are optional and can be used to specify
# non-default value for project and user format variables.
# Defaults are respectively 'project_name' and 'user_name'
#
# setup_colorized_logging something.conf SOMESECTION
function setup_colorized_logging {
    local conf_file=$1
    local conf_section=$2
    local project_var=${3:-"project_name"}
    local user_var=${4:-"user_name"}
    # Add color to logging output
    iniset $conf_file $conf_section logging_context_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [%(request_id)s %("$user_var")s %("$project_var")s%(color)s] %(instance)s%(color)s%(message)s"
    iniset $conf_file $conf_section logging_default_format_string "%(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s"
    iniset $conf_file $conf_section logging_debug_format_suffix "from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d"
    iniset $conf_file $conf_section logging_exception_prefix "%(color)s%(asctime)s.%(msecs)03d TRACE %(name)s %(instance)s"
}

# These functions are provided for basic fall-back functionality for
# projects that include parts of DevStack (Grenade).  stack.sh will
# override these with more specific versions for DevStack (with fancy
# spinners, etc).  We never override an existing version
if ! function_exists echo_summary; then
    function echo_summary {
        echo $@
    }
fi
if ! function_exists echo_nolog; then
    function echo_nolog {
        echo $@
    }
fi


# create_disk - Create backing disk
function create_disk {
    local node_number
    local disk_image=${1}
    local storage_data_dir=${2}
    local loopback_disk_size=${3}

    # Create a loopback disk and format it to XFS.
    if [[ -e ${disk_image} ]]; then
        if egrep -q ${storage_data_dir} /proc/mounts; then
            sudo umount ${storage_data_dir}/drives/sdb1
            sudo rm -f ${disk_image}
        fi
    fi

    sudo mkdir -p ${storage_data_dir}/drives/images

    sudo truncate -s ${loopback_disk_size} ${disk_image}

    # Make a fresh XFS filesystem. Use bigger inodes so xattr can fit in
    # a single inode. Keeping the default inode size (256) will result in multiple
    # inodes being used to store xattr. Retrieving the xattr will be slower
    # since we have to read multiple inodes. This statement is true for both
    # Swift and Ceph.
    sudo mkfs.xfs -f -i size=1024 ${disk_image}

    # Mount the disk with mount options to make it as efficient as possible
    if ! egrep -q ${storage_data_dir} /proc/mounts; then
        sudo mount -t xfs -o loop,noatime,nodiratime,nobarrier,logbufs=8  \
            ${disk_image} ${storage_data_dir}
    fi
}

# Restore xtrace
$XTRACE

# Local variables:
# mode: shell-script
# End: