Separate base images into different folders

This moves a few things around. Namely centos/fedora-rdo-base becomes
centos/rdo/base
fedora/rdo/base

I have also separated out RHEL.

Moves the current scripts in "base" to a "common" folder common to all
images and then recreates the appropriate links to allow all the
containers to build the same way they did before.

This removes all .buildconfs in the system (though they are still usable)

Partially Implements: blueprint refactor-base-image-layout

Co-Authored-By: Martin André <martin.andre@kvhasia.com>
Change-Id: Id63eac1eb9893ceb775c28bf22842dede85c214a
This commit is contained in:
Sam Yaple 2015-05-19 05:42:26 -05:00 committed by Martin André
parent 318f2f451f
commit 23a7fa2869
67 changed files with 265 additions and 224 deletions

View File

@ -1,170 +0,0 @@
#!/bin/bash
. /opt/kolla/service_hosts.sh
# Set some generally useful defaults.
MY_IP=$(ip route get $(ip route | awk '$1 == "default" {print $3}') |
awk '$4 == "src" {print $5}')
: ${PUBLIC_IP:=${MY_IP}}
# Iterate over a list of variable names and exit if one is
# undefined.
check_required_vars() {
for var in $*; do
if [ -z "${!var}" ]; then
echo "ERROR: missing $var" >&2
exit 1
fi
done
}
# The usage of the wait_for function looks like the following
# wait_for LOOPS_NUMBER SLEEP_TIME ARGS
#
# The ARGS are read and concatenated together into a single command and the
# command is executed in a loop until it succeeds or reaches the max number of
# attempts (LOOPS_NUMBER).
#
# Optional variables SUCCESSFUL_MATCH_OUTPUT and FAIL_MATCH_OUTPUT variable may
# also be set to control if the loop exits early if the commands stdout/stderr
# matches the supplied regex string. Consider using the `wait_for_output` and
# `wait_for_output_unless` functions in case there is a need to check for the
# command output.
#
# The script exits on failure, either when output contains string identified as
# failure, or when it reaches a timeout.
#
# Examples:
# wait_for 30 10 ping -c 1 192.0.2.2
# wait_for 10 1 ls file_we_are_waiting_for
# wait_for 10 3 date \| grep 8
wait_for() {
local loops=${1:-""}
local sleeptime=${2:-""}
FAIL_MATCH_OUTPUT=${FAIL_MATCH_OUTPUT:-""}
SUCCESSFUL_MATCH_OUTPUT=${SUCCESSFUL_MATCH_OUTPUT:-""}
shift 2 || true
local command="$@"
if [ -z "$loops" -o -z "$sleeptime" -o -z "$command" ]; then
echo "wait_for is missing a required parameter"
exit 1
fi
local i=0
while [ $i -lt $loops ]; do
i=$((i + 1))
local status=0
local output=$(eval $command 2>&1) || status=$?
if [[ -n "$SUCCESSFUL_MATCH_OUTPUT" ]] \
&& [[ $output =~ $SUCCESSFUL_MATCH_OUTPUT ]]; then
return 0
elif [[ -n "$FAIL_MATCH_OUTPUT" ]] \
&& [[ $output =~ $FAIL_MATCH_OUTPUT ]]; then
echo "Command output matched '$FAIL_MATCH_OUTPUT'."
exit 1
elif [[ -z "$SUCCESSFUL_MATCH_OUTPUT" ]] && [[ $status -eq 0 ]]; then
return 0
fi
sleep $sleeptime
done
local seconds=$((loops * sleeptime))
printf 'Timing out after %d seconds:\ncommand=%s\nOUTPUT=%s\n' \
"$seconds" "$command" "$output"
exit 1
}
# Helper function to `wait_for` that only succeeds when the given regex is
# matching the command's output. Exit early with a failure when the second
# supplied regexp is matching the output.
#
# Example:
# wait_for_output_unless CREATE_COMPLETE CREATE_FAIL 30 10 heat stack-show undercloud
wait_for_output_unless() {
SUCCESSFUL_MATCH_OUTPUT=$1
FAIL_MATCH_OUTPUT=$2
shift 2
wait_for $@
local status=$?
unset SUCCESSFUL_MATCH_OUTPUT
unset FAIL_MATCH_OUTPUT
return $status
}
# Helper function to `wait_for` that only succeeds when the given regex is
# matching the command's output.
#
# Example:
# wait_for_output CREATE_COMPLETE 30 10 heat stack-show undercloud
wait_for_output() {
local expected_output=$1
shift
wait_for_output_unless $expected_output '' $@
}
# Check if we receive a successful response from corresponding OpenStack
# service endpoint.
check_for_os_service_endpoint() {
local name=$1
local host_var=$2
local port_var=$3
local api_version=$4
check_required_vars $host_var $port_var
local endpoint="http://${!host_var}:${!port_var}/$api_version"
curl -sf -o /dev/null "$endpoint" || {
echo "ERROR: $name is not available @ $endpoint" >&2
return 1
}
echo "$name is active @ $endpoint"
}
check_for_os_service_running() {
local service=$1
local args=
case $service in
("glance") args="GLANCE_API_SERVICE_HOST GLANCE_API_SERVICE_PORT" ;;
("keystone") args="KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_PUBLIC_SERVICE_PORT v2.0" ;;
("neutron") args="NEUTRON_SERVER_SERVICE_HOST NEUTRON_SERVER_SERVICE_PORT" ;;
("nova") args="NOVA_API_SERVICE_HOST NOVA_API_SERVICE_PORT" ;;
(*)
echo "Unknown service $service"
return 1 ;;
esac
check_for_os_service_endpoint $service $args
}
fail_unless_os_service_running() {
check_for_os_service_running $@ || exit $?
}
# Check if we receive a successful response from the database server.
# Optionally takes a database name to check for. Defaults to 'mysql'.
check_for_db() {
local database=${1:-mysql}
check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD
mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" \
-e "select 1" $database > /dev/null 2>&1 || {
echo "ERROR: database $database is not available @ $MARIADB_SERVICE_HOST" >&2
return 1
}
echo "database is active @ ${MARIADB_SERVICE_HOST}"
}
fail_unless_db() {
check_for_db $@ || exit $?
}
# Dump shell environment to a file
dump_vars() {
set -o posix
set > /pid_$$_vars.sh
set +o posix
}

View File

@ -0,0 +1 @@
../../../common/kolla-common.sh

View File

@ -1,45 +0,0 @@
#!/bin/bash
# Kubernetes currently creates FOO_SERVICE_HOST and FOO_SERVICE_PORT env vars
# as part of starting the containers. However this is not done when starting
# them with plain docker. Defaulting variables to their common version if
# they're not already set allows the usage of --link in plain 'docker run' to
# wire together containers.
: ${BARBICAN_ADMIN_SERVICE_HOST:=$BARBICAN_ADMIN_PORT_9312_TCP_ADDR}
: ${BARBICAN_ADMIN_SERVICE_PORT:=9312}
: ${BARBICAN_PUBLIC_SERVICE_HOST:=$BARBICAN_PUBLIC_PORT_9311_TCP_ADDR}
: ${BARBICAN_PUBLIC_SERVICE_PORT:=9311}
: ${CEILOMETER_API_SERVICE_HOST:=$CEILOMETER_API_PORT_8777_TCP_ADDR}
: ${CEILOMETER_API_SERVICE_PORT:=8777}
: ${GLANCE_API_SERVICE_HOST:=$GLANCE_API_PORT_9292_TCP_ADDR}
: ${GLANCE_API_SERVICE_PORT:=9292}
: ${GLANCE_REGISTRY_SERVICE_HOST:=$GLANCE_REGISTRY_PORT_9191_TCP_ADDR}
: ${GLANCE_REGISTRY_SERVICE_PORT:=9191}
: ${HEAT_API_SERVICE_HOST:=$HEAT_API_PORT_8004_TCP_ADDR}
: ${HEAT_API_SERVICE_PORT:=8004}
: ${HORIZON_SERVICE_HOST:=$HORIZON_PORT_80_TCP_ADDR}
: ${HORIZON_SERVICE_PORT:=80}
: ${KEYSTONE_ADMIN_SERVICE_HOST:=$KEYSTONE_PORT_35357_TCP_ADDR}
: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$KEYSTONE_PORT_5000_TCP_ADDR}
: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
: ${MARIADB_SERVICE_HOST:=$MARIADB_PORT_3306_TCP_ADDR}
: ${MARIADB_SERVICE_PORT:=3306}
: ${MONGODB_SERVICE_HOST:=$MONGODB_PORT_27017_TCP_ADDR}
: ${MONGODB_SERVICE_PORT:=27017}
: ${NEUTRON_SERVER_SERVICE_HOST:=$NEUTRON_SERVER_PORT_9696_TCP_ADDR}
: ${NEUTRON_SERVER_SERVICE_PORT:=9696}
: ${NOVA_API_SERVICE_HOST:=$NOVA_API_PORT_8774_TCP_ADDR}
: ${NOVA_API_SERVICE_PORT:=8774}
: ${NOVA_EC2_API_SERVICE_HOST:=$NOVA_EC2_API_PORT_8773_TCP_ADDR}
: ${NOVA_EC2_API_SERVICE_PORT:=8773}
: ${NOVA_LIBVIRT_SERVICE_HOST:=$NOVA_LIBVIRT_PORT_16509_TCP_ADDR}
: ${NOVA_LIBVIRT_SERVICE_PORT:=16509}
: ${NOVA_METADATA_API_SERVICE_HOST:=$NOVA_METADATA_API_PORT_8775_TCP_ADDR}
: ${NOVA_METADATA_API_SERVICE_PORT:=8775}
: ${RABBITMQ_SERVICE_HOST:=$RABBITMQ_PORT_5672_TCP_ADDR}
: ${RABBITMQ_SERVICE_PORT:=5672}
: ${ZAQAR_SERVER_SERVICE_HOST:=$ZAQAR_SERVER_PORT_8888_TCP_ADDR}
: ${ZAQAR_SERVER_SERVICE_PORT:=8888}

View File

@ -0,0 +1 @@
../../../common/service_hosts.sh

View File

@ -1 +0,0 @@
PREFIX=

View File

@ -1 +0,0 @@
../base/kolla-common.sh

View File

@ -1 +0,0 @@
../base/service_hosts.sh

View File

@ -1 +0,0 @@
centos-binary-base/

View File

@ -1 +0,0 @@
PREFIX=

View File

@ -1 +0,0 @@
../base/kolla-common.sh

View File

@ -1 +0,0 @@
../base/service_hosts.sh

View File

@ -1 +0,0 @@
fedora-binary-base

View File

@ -0,0 +1,170 @@
#!/bin/bash
. /opt/kolla/service_hosts.sh
# Set some generally useful defaults.
MY_IP=$(ip route get $(ip route | awk '$1 == "default" {print $3}') |
awk '$4 == "src" {print $5}')
: ${PUBLIC_IP:=${MY_IP}}
# Iterate over a list of variable names and exit if one is
# undefined.
check_required_vars() {
for var in $*; do
if [ -z "${!var}" ]; then
echo "ERROR: missing $var" >&2
exit 1
fi
done
}
# The usage of the wait_for function looks like the following
# wait_for LOOPS_NUMBER SLEEP_TIME ARGS
#
# The ARGS are read and concatenated together into a single command and the
# command is executed in a loop until it succeeds or reaches the max number of
# attempts (LOOPS_NUMBER).
#
# Optional variables SUCCESSFUL_MATCH_OUTPUT and FAIL_MATCH_OUTPUT variable may
# also be set to control if the loop exits early if the commands stdout/stderr
# matches the supplied regex string. Consider using the `wait_for_output` and
# `wait_for_output_unless` functions in case there is a need to check for the
# command output.
#
# The script exits on failure, either when output contains string identified as
# failure, or when it reaches a timeout.
#
# Examples:
# wait_for 30 10 ping -c 1 192.0.2.2
# wait_for 10 1 ls file_we_are_waiting_for
# wait_for 10 3 date \| grep 8
wait_for() {
local loops=${1:-""}
local sleeptime=${2:-""}
FAIL_MATCH_OUTPUT=${FAIL_MATCH_OUTPUT:-""}
SUCCESSFUL_MATCH_OUTPUT=${SUCCESSFUL_MATCH_OUTPUT:-""}
shift 2 || true
local command="$@"
if [ -z "$loops" -o -z "$sleeptime" -o -z "$command" ]; then
echo "wait_for is missing a required parameter"
exit 1
fi
local i=0
while [ $i -lt $loops ]; do
i=$((i + 1))
local status=0
local output=$(eval $command 2>&1) || status=$?
if [[ -n "$SUCCESSFUL_MATCH_OUTPUT" ]] \
&& [[ $output =~ $SUCCESSFUL_MATCH_OUTPUT ]]; then
return 0
elif [[ -n "$FAIL_MATCH_OUTPUT" ]] \
&& [[ $output =~ $FAIL_MATCH_OUTPUT ]]; then
echo "Command output matched '$FAIL_MATCH_OUTPUT'."
exit 1
elif [[ -z "$SUCCESSFUL_MATCH_OUTPUT" ]] && [[ $status -eq 0 ]]; then
return 0
fi
sleep $sleeptime
done
local seconds=$((loops * sleeptime))
printf 'Timing out after %d seconds:\ncommand=%s\nOUTPUT=%s\n' \
"$seconds" "$command" "$output"
exit 1
}
# Helper function to `wait_for` that only succeeds when the given regex is
# matching the command's output. Exit early with a failure when the second
# supplied regexp is matching the output.
#
# Example:
# wait_for_output_unless CREATE_COMPLETE CREATE_FAIL 30 10 heat stack-show undercloud
wait_for_output_unless() {
SUCCESSFUL_MATCH_OUTPUT=$1
FAIL_MATCH_OUTPUT=$2
shift 2
wait_for $@
local status=$?
unset SUCCESSFUL_MATCH_OUTPUT
unset FAIL_MATCH_OUTPUT
return $status
}
# Helper function to `wait_for` that only succeeds when the given regex is
# matching the command's output.
#
# Example:
# wait_for_output CREATE_COMPLETE 30 10 heat stack-show undercloud
wait_for_output() {
local expected_output=$1
shift
wait_for_output_unless $expected_output '' $@
}
# Check if we receive a successful response from corresponding OpenStack
# service endpoint.
check_for_os_service_endpoint() {
local name=$1
local host_var=$2
local port_var=$3
local api_version=$4
check_required_vars $host_var $port_var
local endpoint="http://${!host_var}:${!port_var}/$api_version"
curl -sf -o /dev/null "$endpoint" || {
echo "ERROR: $name is not available @ $endpoint" >&2
return 1
}
echo "$name is active @ $endpoint"
}
check_for_os_service_running() {
local service=$1
local args=
case $service in
("glance") args="GLANCE_API_SERVICE_HOST GLANCE_API_SERVICE_PORT" ;;
("keystone") args="KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_PUBLIC_SERVICE_PORT v2.0" ;;
("neutron") args="NEUTRON_SERVER_SERVICE_HOST NEUTRON_SERVER_SERVICE_PORT" ;;
("nova") args="NOVA_API_SERVICE_HOST NOVA_API_SERVICE_PORT" ;;
(*)
echo "Unknown service $service"
return 1 ;;
esac
check_for_os_service_endpoint $service $args
}
fail_unless_os_service_running() {
check_for_os_service_running $@ || exit $?
}
# Check if we receive a successful response from the database server.
# Optionally takes a database name to check for. Defaults to 'mysql'.
check_for_db() {
local database=${1:-mysql}
check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD
mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" \
-e "select 1" $database > /dev/null 2>&1 || {
echo "ERROR: database $database is not available @ $MARIADB_SERVICE_HOST" >&2
return 1
}
echo "database is active @ ${MARIADB_SERVICE_HOST}"
}
fail_unless_db() {
check_for_db $@ || exit $?
}
# Dump shell environment to a file
dump_vars() {
set -o posix
set > /pid_$$_vars.sh
set +o posix
}

45
docker/common/service_hosts.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# Kubernetes currently creates FOO_SERVICE_HOST and FOO_SERVICE_PORT env vars
# as part of starting the containers. However this is not done when starting
# them with plain docker. Defaulting variables to their common version if
# they're not already set allows the usage of --link in plain 'docker run' to
# wire together containers.
: ${BARBICAN_ADMIN_SERVICE_HOST:=$BARBICAN_ADMIN_PORT_9312_TCP_ADDR}
: ${BARBICAN_ADMIN_SERVICE_PORT:=9312}
: ${BARBICAN_PUBLIC_SERVICE_HOST:=$BARBICAN_PUBLIC_PORT_9311_TCP_ADDR}
: ${BARBICAN_PUBLIC_SERVICE_PORT:=9311}
: ${CEILOMETER_API_SERVICE_HOST:=$CEILOMETER_API_PORT_8777_TCP_ADDR}
: ${CEILOMETER_API_SERVICE_PORT:=8777}
: ${GLANCE_API_SERVICE_HOST:=$GLANCE_API_PORT_9292_TCP_ADDR}
: ${GLANCE_API_SERVICE_PORT:=9292}
: ${GLANCE_REGISTRY_SERVICE_HOST:=$GLANCE_REGISTRY_PORT_9191_TCP_ADDR}
: ${GLANCE_REGISTRY_SERVICE_PORT:=9191}
: ${HEAT_API_SERVICE_HOST:=$HEAT_API_PORT_8004_TCP_ADDR}
: ${HEAT_API_SERVICE_PORT:=8004}
: ${HORIZON_SERVICE_HOST:=$HORIZON_PORT_80_TCP_ADDR}
: ${HORIZON_SERVICE_PORT:=80}
: ${KEYSTONE_ADMIN_SERVICE_HOST:=$KEYSTONE_PORT_35357_TCP_ADDR}
: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$KEYSTONE_PORT_5000_TCP_ADDR}
: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
: ${MARIADB_SERVICE_HOST:=$MARIADB_PORT_3306_TCP_ADDR}
: ${MARIADB_SERVICE_PORT:=3306}
: ${MONGODB_SERVICE_HOST:=$MONGODB_PORT_27017_TCP_ADDR}
: ${MONGODB_SERVICE_PORT:=27017}
: ${NEUTRON_SERVER_SERVICE_HOST:=$NEUTRON_SERVER_PORT_9696_TCP_ADDR}
: ${NEUTRON_SERVER_SERVICE_PORT:=9696}
: ${NOVA_API_SERVICE_HOST:=$NOVA_API_PORT_8774_TCP_ADDR}
: ${NOVA_API_SERVICE_PORT:=8774}
: ${NOVA_EC2_API_SERVICE_HOST:=$NOVA_EC2_API_PORT_8773_TCP_ADDR}
: ${NOVA_EC2_API_SERVICE_PORT:=8773}
: ${NOVA_LIBVIRT_SERVICE_HOST:=$NOVA_LIBVIRT_PORT_16509_TCP_ADDR}
: ${NOVA_LIBVIRT_SERVICE_PORT:=16509}
: ${NOVA_METADATA_API_SERVICE_HOST:=$NOVA_METADATA_API_PORT_8775_TCP_ADDR}
: ${NOVA_METADATA_API_SERVICE_PORT:=8775}
: ${RABBITMQ_SERVICE_HOST:=$RABBITMQ_PORT_5672_TCP_ADDR}
: ${RABBITMQ_SERVICE_PORT:=5672}
: ${ZAQAR_SERVER_SERVICE_HOST:=$ZAQAR_SERVER_PORT_8888_TCP_ADDR}
: ${ZAQAR_SERVER_SERVICE_PORT:=8888}

View File

@ -1 +0,0 @@
centos

View File

@ -0,0 +1 @@
../../centos/binary/barbican

View File

@ -0,0 +1 @@
../../../common/kolla-common.sh

View File

@ -0,0 +1 @@
../../../common/service_hosts.sh

View File

@ -0,0 +1 @@
../../centos/binary/ceilometer

1
docker/fedora/binary/cinder Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/cinder

View File

@ -0,0 +1 @@
../../centos/binary/designate

View File

@ -0,0 +1 @@
../../centos/binary/docker-compose

1
docker/fedora/binary/glance Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/glance

View File

@ -0,0 +1 @@
../../centos/binary/hautoproxy

1
docker/fedora/binary/heat Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/heat

View File

@ -0,0 +1 @@
../../centos/binary/horizon

View File

@ -0,0 +1 @@
../../centos/binary/keystone

1
docker/fedora/binary/magnum Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/magnum

View File

@ -0,0 +1 @@
../../centos/binary/mariadb-app

View File

@ -0,0 +1 @@
../../centos/binary/mariadb-data

View File

@ -0,0 +1 @@
../../centos/binary/mongodb

View File

@ -0,0 +1 @@
../../centos/binary/neutron

View File

@ -0,0 +1 @@
../../centos/binary/nova-base

View File

@ -0,0 +1 @@
../../centos/binary/nova-compute

View File

@ -0,0 +1 @@
../../centos/binary/nova-controller

View File

@ -0,0 +1 @@
../../centos/binary/rabbitmq

1
docker/fedora/binary/swift Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/swift

1
docker/fedora/binary/zaqar Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/zaqar

1
docker/fedora/rdo Symbolic link
View File

@ -0,0 +1 @@
binary

1
docker/rhel/binary/barbican Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/barbican

View File

@ -0,0 +1 @@
../../../common/kolla-common.sh

View File

@ -0,0 +1 @@
../../../common/service_hosts.sh

View File

@ -0,0 +1 @@
../../centos/binary/ceilometer

1
docker/rhel/binary/cinder Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/cinder

View File

@ -0,0 +1 @@
../../centos/binary/designate

View File

@ -0,0 +1 @@
../../centos/binary/docker-compose

1
docker/rhel/binary/glance Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/glance

View File

@ -0,0 +1 @@
../../centos/binary/hautoproxy

1
docker/rhel/binary/heat Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/heat

1
docker/rhel/binary/horizon Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/horizon

1
docker/rhel/binary/keystone Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/keystone

1
docker/rhel/binary/magnum Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/magnum

View File

@ -0,0 +1 @@
../../centos/binary/mariadb-app

View File

@ -0,0 +1 @@
../../centos/binary/mariadb-data

1
docker/rhel/binary/mongodb Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/mongodb

1
docker/rhel/binary/neutron Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/neutron

View File

@ -0,0 +1 @@
../../centos/binary/nova-base

View File

@ -0,0 +1 @@
../../centos/binary/nova-compute

View File

@ -0,0 +1 @@
../../centos/binary/nova-controller

1
docker/rhel/binary/rabbitmq Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/rabbitmq

1
docker/rhel/binary/swift Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/swift

1
docker/rhel/binary/zaqar Symbolic link
View File

@ -0,0 +1 @@
../../centos/binary/zaqar

1
docker/rhel/osp Symbolic link
View File

@ -0,0 +1 @@
binary