Improve Azure blob/file mount logic

- Add retries to mount commands
- Simplify through script template
This commit is contained in:
Fred Park 2019-11-13 07:09:26 +00:00
Родитель ceb8b36853
Коммит 2b4bb852c3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3C4D545F457737EB
3 изменённых файлов: 139 добавлений и 61 удалений

Просмотреть файл

@ -218,6 +218,10 @@ _DOCKER_EXEC_TASK_RUNNER_FILE = (
'shipyard_docker_exec_task_runner.sh',
pathlib.Path(_ROOT_PATH, 'scripts/shipyard_docker_exec_task_runner.sh')
)
_AZURE_STORAGE_MOUNT_FILE = (
'shipyard_azure_storage_mount.sh',
pathlib.Path(_ROOT_PATH, 'scripts/shipyard_azure_storage_mount.sh')
)
_GLUSTERPREP_FILE = (
'shipyard_glusterfs_on_compute.sh',
pathlib.Path(_ROOT_PATH, 'scripts/shipyard_glusterfs_on_compute.sh')
@ -661,7 +665,7 @@ def _setup_azureblob_mounts(blob_client, config, bc):
"""
tmpmount = settings.temp_disk_mountpoint(config)
# construct mount commands
cmds = []
mounts = []
sdv = settings.global_resources_shared_data_volumes(config)
for svkey in sdv:
if settings.is_shared_data_volume_azure_blob(sdv, svkey):
@ -669,52 +673,45 @@ def _setup_azureblob_mounts(blob_client, config, bc):
config,
settings.azure_storage_account_settings(sdv, svkey))
cont = settings.azure_blob_container_name(sdv, svkey)
hmp = settings.azure_blob_host_mount_path(sa.account, cont)
sas = storage.create_blob_container_saskey(
sa, cont, 'egress', create_container=True)
tmpmp = '{}/blobfuse-tmp/{}-{}'.format(tmpmount, sa.account, cont)
cmds.append('mkdir -p {}'.format(hmp))
cmds.append('chmod 0770 {}'.format(hmp))
cmds.append('mkdir -p {}'.format(tmpmp))
cmds.append('chown _azbatch:_azbatchgrp {}'.format(tmpmp))
cmds.append('chmod 0770 {}'.format(tmpmp))
cmds.append('export AZURE_STORAGE_ACCOUNT="{}"'.format(sa.account))
cmds.append('export AZURE_STORAGE_SAS_TOKEN="{}"'.format(sas))
cmd = (
'blobfuse {hmp} --container-name={cont} '
'--tmp-path={tmpmp} -o allow_other'
).format(hmp=hmp, cont=cont, tmpmp=tmpmp)
# add any additional mount options
mo = settings.shared_data_volume_mount_options(sdv, svkey)
if util.is_not_empty(mo):
opts = []
for opt in mo:
if opt.strip() == '-o allow_other':
continue
opts.append(opt)
cmd = '{} {}'.format(cmd, ' '.join(opts))
if '-o attr_timeout=' not in cmd:
cmd = '{} -o attr_timeout=240'.format(cmd)
if '-o entry_timeout=' not in cmd:
cmd = '{} -o entry_timeout=240'.format(cmd)
if '-o negative_timeout=' not in cmd:
cmd = '{} -o negative_timeout=120'.format(cmd)
cmds.append(cmd)
# create file share mount command script
if util.is_none_or_empty(cmds):
opts = ' '.join(mo or [])
if '-o allow_other' not in opts:
opts = '{} -o allow_other'.format(opts)
if '-o attr_timeout=' not in opts:
opts = '{} -o attr_timeout=240'.format(opts)
if '-o entry_timeout=' not in opts:
opts = '{} -o entry_timeout=240'.format(opts)
if '-o negative_timeout=' not in opts:
opts = '{} -o negative_timeout=120'.format(opts)
mount = {
'sa': sa,
'container': cont,
'sas': sas,
'user_mp': tmpmount,
'options': opts,
}
mounts.append(mount)
# create blob mount command script
if util.is_none_or_empty(mounts):
raise RuntimeError('Generated Azure blob mount commands are invalid')
with _AZURE_STORAGE_MOUNT_FILE[1].open('r') as f:
template = f.readlines()
newline = '\n'
volcreate = _generate_azure_mount_script_name(
bc.account, settings.pool_id(config), False, False)
newline = '\n'
with volcreate.open('w', newline=newline) as f:
f.write('#!/usr/bin/env bash')
f.write(newline)
f.write('set -e')
f.write(newline)
f.write('set -o pipefail')
f.write(newline)
for cmd in cmds:
f.write(cmd)
for line in template:
f.write(line)
for mount in mounts:
f.write('prep_blob_mount_dirs "{}" "{}" "{}"'.format(
mount['user_mp'], mount['sa'].account, mount['container']))
f.write(newline)
f.write('mount_blob_container "{}" "{}" "{}" "{}" {}'.format(
mount['user_mp'], mount['sa'].account, mount['container'],
mount['sas'], mount['options']))
f.write(newline)
return volcreate
@ -755,17 +752,10 @@ def _setup_azurefile_mounts(blob_client, config, bc, is_windows):
hmp=hmp, sa=sa.account, ep=sa.endpoint, share=share)
)
else:
cmd = (
'mount -t cifs //{sa}.file.{ep}/{share} {hmp} -o '
'vers=3.0,username={sa},password={sakey},'
'serverino'
).format(
sa=sa.account, ep=sa.endpoint, share=share, hmp=hmp,
sakey=sa.account_key)
# add any additional mount options
mo = settings.shared_data_volume_mount_options(sdv, svkey)
opts = []
if util.is_not_empty(mo):
opts = []
# retain backward compatibility with filemode/dirmode
# options from the old Azure File Docker volume driver
for opt in mo:
@ -776,9 +766,12 @@ def _setup_azurefile_mounts(blob_client, config, bc, is_windows):
opts.append('dir_mode={}'.format(tmp[1]))
else:
opts.append(opt)
cmd = '{},{}'.format(cmd, ','.join(opts))
if not is_windows:
cmds.append('mkdir -p {}'.format(hmp))
opts = ','.join(opts)
cmd = {
'sa': sa,
'share': share,
'options': opts,
}
cmds.append(cmd)
# create file share mount command script
if util.is_none_or_empty(cmds):
@ -790,16 +783,22 @@ def _setup_azurefile_mounts(blob_client, config, bc, is_windows):
if is_windows:
f.write('@echo off')
f.write(newline)
for cmd in cmds:
f.write(cmd)
f.write(newline)
else:
f.write('#!/usr/bin/env bash')
f.write(newline)
f.write('set -e')
f.write(newline)
f.write('set -o pipefail')
f.write(newline)
for cmd in cmds:
f.write(cmd)
f.write(newline)
with _AZURE_STORAGE_MOUNT_FILE[1].open('r') as inf:
template = inf.readlines()
for line in template:
f.write(line)
for mount in cmds:
f.write('prep_file_mount_dirs "{}" "{}"'.format(
mount['sa'].account, mount['share']))
f.write(newline)
f.write('mount_file_share "{}" "{}" "{}" "{}" "{}"'.format(
mount['sa'].account, mount['sa'].endpoint,
mount['sa'].account_key, mount['share'], mount['options']))
f.write(newline)
return volcreate

Просмотреть файл

@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -e
set -o pipefail
MOUNT_DIR="$AZ_BATCH_NODE_ROOT_DIR/mounts"
execute_command_with_retry() {
set +e
local retries=$1
shift
local fatal=$1
shift
local rc
while [ "$retries" -gt 0 ]; do
"$@"
rc=$?
if [ "$rc" -eq 0 ]; then
break
fi
retries=$((retries-1))
if [ $retries -eq 0 ]; then
echo "Could not execute command: $*"
if [ "$fatal" -eq 1 ]; then
exit $rc
else
break
fi
fi
sleep 1
done
set -e
}
prep_blob_mount_dirs() {
local bftmp="${1}/blobfuse-tmp/${2}-${3}"
local hmp="${MOUNT_DIR}/azblob-${2}-${3}"
mkdir -p "$bftmp"
chmod 0770 "$bftmp"
mkdir -p "$hmp"
chmod 0770 "$hmp"
}
mount_blob_container() {
local container="$3"
local bftmp="${1}/blobfuse-tmp/${2}-${container}"
local hmp="${MOUNT_DIR}/azblob-${2}-${container}"
export AZURE_STORAGE_ACCOUNT="$2"
export AZURE_STORAGE_SAS_TOKEN="$4"
shift 4
echo "Mounting blob container $container (sa=$AZURE_STORAGE_ACCOUNT) with options: $*"
# shellcheck disable=SC2068
execute_command_with_retry 15 1 blobfuse "$hmp" --container-name="${container}" --tmp-path="${bftmp}" $@
}
prep_file_mount_dirs() {
local hmp="${MOUNT_DIR}/azfile-${1}-${2}"
mkdir -p "$hmp"
chmod 0770 "$hmp"
}
mount_file_share() {
local sa="$1"
local ep="$2"
local sakey="$3"
local share="$4"
local opts="$5"
local hmp="${MOUNT_DIR}/azfile-${sa}-${share}"
local options="vers=3.0,username=${sa},password=${sakey}"
if [ -n "$opts" ]; then
options="${options},${opts}"
fi
echo "Mounting file share $share (sa=$sa) with options: $opts"
execute_command_with_retry 15 1 mount -t cifs "//${sa}.file.${ep}/${share}" "${hmp}" -o "$options"
}

Просмотреть файл

@ -554,15 +554,18 @@ execute_command_with_retry() {
shift
local fatal=$1
shift
local rc
while [ "$retries" -gt 0 ]; do
if "$@"; then
"$@"
rc=$?
if [ "$rc" -eq 0 ]; then
break
fi
retries=$((retries-1))
if [ $retries -eq 0 ]; then
log ERROR "Could not execute command: $*"
if [ "$fatal" -eq 1 ]; then
exit 1
exit $rc
else
break
fi