Last active
December 8, 2020 23:28
-
-
Save JamesOBenson/1468d819fb18e178b7f524af2377f577 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
MYDNS="8.8.8.8" | |
DATE=$(date '+%Y-%m-%d') | |
UBUNTU1_URL="http://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img" | |
UBUNTU2_URL="http://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64.img" | |
CIRROS_URL="http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img" | |
CENTOS_URL="http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2c" | |
VOLUME_SIZE=10 | |
NEW_VOLUME_SIZE=15 | |
VOLUME_NAME=$(cat /proc/sys/kernel/random/uuid) | |
INSTANCE_NAME=$(cat /proc/sys/kernel/random/uuid) | |
KEYPAIR_NAME="test_keypair" | |
if [ -f "admin-openrc.sh" ]; then source admin-openrc.sh | |
echo "admin-openrc.sh found" | |
elif [ -f "openrc.sh" ]; then source openrc.sh | |
echo "openrc.sh found..." | |
else echo "No openrc files found" | |
exit 1 | |
fi | |
function one_time () { | |
echo "" | |
echo "One time install... (openstack clients, cirros, flavors)" | |
echo "" | |
pip install --user python-openstackclient | |
} | |
function read_back (){ | |
MYARRAY=("$@") | |
for i in "${MYARRAY[@]}"; | |
do | |
echo "$i" | |
done | |
} | |
function choice_option () { | |
mychoices=("$@") | |
IFS=' ' read -a choices <<< "$mychoices" | |
PS3="Please enter your choice: " | |
select answer in "${choices[@]}"; do | |
for item in "${choices[@]}"; do | |
if [[ $item == $answer ]]; then | |
break 2 | |
fi | |
done | |
done | |
echo "$answer" | |
} | |
function read_image (){ | |
IMAGE_LIST=($(openstack image list -c Name -f value)) | |
echo "${IMAGE_LIST[@]}" | |
} | |
function temp () { | |
instances="$( (read_instances) )" | |
echo $instances | |
if [ -z $instances ]; then echo "no instances" | |
else echo "Please choose an instance to attach the volume to:" | |
INSTANCE_NAME=$(choice_option "$( (read_instances) )") | |
fi | |
echo "TESTING HERE." | |
} | |
function create_image (){ | |
echo "What OS do you want to upload?" | |
options=("CentOS_7" "Ubuntu_16.04LTS" "CirrOS" "Ubuntu_18.04LTS") | |
select OPERATING_SYSTEM in "${options[@]}" | |
do | |
case $OPERATING_SYSTEM in | |
"Ubuntu_16.04LTS" ) | |
IMAGE_LIST="$(openstack image list | awk '{print $4}' |grep -ie $OPERATING_SYSTEM)" | |
[[ ! -z $IMAGE_LIST ]] && echo "Ubuntu image already exists" && exit 0 | |
echo "Downloading Ubuntu 16.04 LTS (Xenial) Image" | |
wget $UBUNTU1_URL -O UbuntuXenial-$DATE.img | |
if [[ ! -f UbuntuXenial-$DATE.img ]]; then | |
echo "File could not be downloaded!" | |
exit 1 | |
fi | |
openstack image create --disk-format qcow2 --container-format bare --public --min-disk 5 --min-ram 2048 --file UbuntuXenial-$DATE.img "Ubuntu_16.04LTS" | |
break;; | |
"Ubuntu_18.04LTS" ) | |
IMAGE_LIST="$(openstack image list | awk '{print $4}' |grep -ie $OPERATING_SYSTEM)" | |
[[ ! -z $IMAGE_LIST ]] && echo "Ubuntu image already exists" && exit 0 | |
echo "Downloading Ubuntu 18.04 LTS (Bionic) Image" | |
wget $UBUNTU2_URL -O UbuntuBionic-$DATE.img | |
if [[ ! -f UbuntuBionic-$DATE.img ]]; then | |
echo "File could not be downloaded!" | |
exit 1 | |
fi | |
openstack image create --disk-format qcow2 --container-format bare --public --min-disk 5 --min-ram 2048 --file UbuntuBionic-$DATE.img "Ubuntu_18.04LTS" | |
break;; | |
"CentOS_7" ) | |
IMAGE_LIST="$(openstack image list | awk '{print $4}' |grep -ie $OPERATING_SYSTEM)" | |
[[ ! -z $IMAGE_LIST ]] && echo "CentOS 7 image already exists" && exit 0 | |
echo "Downloading CentOS 7 Image" | |
wget $CENTOS_URL -O CentOS_7-$DATE.qcow2c | |
if [[ ! -f CentOS_7-$DATE.qcow2c ]]; then | |
echo "File could not be downloaded!" | |
exit 1 | |
fi | |
openstack image create --disk-format qcow2 --container-format bare --public --min-disk 5 --min-ram 2048 --file CentOS_7-$DATE.qcow2c "CentOS_7" | |
break;; | |
"CirrOS") | |
IMAGE_LIST="$(openstack image list | awk '{print $4}' |grep -ie $OPERATING_SYSTEM)" | |
[[ ! -z $IMAGE_LIST ]] && echo "CirrOS image already exists" && exit 0 | |
echo "Downloading CirrOS 0.4.0 Image" | |
wget $CIRROS_URL -O CirrOS-$DATE.img | |
if [[ ! -f CirrOS-$DATE.img ]]; then | |
echo "File could not be downloaded!" | |
exit 1 | |
fi | |
openstack image create --disk-format qcow2 --container-format bare --public --file CirrOS-$DATE.img "CirrOS" | |
break;; | |
* ) echo "Invalid option";; | |
esac | |
done | |
} | |
function create_flavors () { | |
openstack flavor create --id 1 --vcpus 1 --ram 2048 --disk 20 gp1.small | |
openstack flavor create --id 2 --vcpus 2 --ram 4096 --disk 20 gp1.medium | |
openstack flavor create --id 3 --vcpus 4 --ram 9216 --disk 20 gp1.large | |
openstack flavor create --id 4 --vcpus 1 --ram 1024 --disk 20 cb1.small | |
openstack flavor create --id 5 --vcpus 2 --ram 2048 --disk 20 cb1.medium | |
openstack flavor create --id 6 --vcpus 4 --ram 4096 --disk 20 cb1.large | |
openstack flavor create --id 7 --vcpus 1 --ram 3072 --disk 20 mb1.small | |
openstack flavor create --id 8 --vcpus 2 --ram 6144 --disk 20 mb1.medium | |
openstack flavor create --id 9 --vcpus 4 --ram 12288 --disk 20 mb1.large | |
openstack flavor create --id 11 --vcpus 1 --ram 2048 --disk 40 gp2.small | |
openstack flavor create --id 12 --vcpus 2 --ram 4096 --disk 40 gp2.medium | |
openstack flavor create --id 13 --vcpus 4 --ram 9216 --disk 40 gp2.large | |
openstack flavor create --id 14 --vcpus 1 --ram 1024 --disk 40 cb2.small | |
openstack flavor create --id 15 --vcpus 2 --ram 2048 --disk 40 cb2.medium | |
openstack flavor create --id 16 --vcpus 4 --ram 4096 --disk 40 cb2.large | |
openstack flavor create --id 17 --vcpus 1 --ram 3072 --disk 40 mb2.small | |
openstack flavor create --id 18 --vcpus 2 --ram 6144 --disk 40 mb2.medium | |
openstack flavor create --id 19 --vcpus 4 --ram 12288 --disk 40 mb2.large | |
openstack flavor create --id 100 --vcpus 1 --ram 256 --disk 1 ref.nano | |
openstack flavor create --id 101 --vcpus 2 --ram 512 --disk 2 ref.micro | |
} | |
function read_flavors () { | |
FLAVOR_LIST=($(openstack flavor list -c Name -f value)) | |
echo "${FLAVOR_LIST[@]}" | |
} | |
function read_instances () { | |
INSTANCE_LIST=($(openstack server list -c Name -f value)) | |
echo "${INSTANCE_LIST[@]}" | |
} | |
function read_networks () { | |
NETWORK_LIST=($(openstack network list -c Name -f value)) | |
echo "${NETWORK_LIST[@]}" | |
} | |
function create_admin_networking () { | |
echo "" | |
echo "Creating admin network for public use (NOT FOR LOCAL ACCOUNTS) ..." | |
echo " Note: This is typically a one-time need ..." | |
echo "" | |
tenant=$(openstack project list -f value -c ID --user admin) | |
echo "Please enter the public network that will be used for floating IP's in the following format: 10.245.126" | |
read -r public_network | |
openstack network create --share --project "${tenant}" --external --provider-network-type flat --provider-physical-network physnet1 public | |
#if segmented network{vlan,vxlan,gre}: --provider:segmentation_id ${segment_id} | |
openstack subnet create --project "${tenant}" --subnet-range "${public_network}".0/24 --allocation-pool start="${public_network}".45,end="${public_network}".249 --dns-nameserver "${MYDNS}" --gateway "${public_network}".253 --network public public_subnet | |
# if you need a specific route to get "out" of your public network: --host-route destination=10.0.0.0/8,nexthop=10.1.10.254 | |
} | |
function read_admin_networking () { | |
EXTERNAL_ID=$(openstack network list --external --long -f value -c ID) | |
echo "$EXTERNAL_ID" | |
} | |
function project_list () { | |
PROJECT_LIST=($(openstack project list -f value -c Name)) | |
echo "${PROJECT_LIST[@]}" | |
} | |
function create_group_user () { | |
echo "User Name? (Default First Initial, Last Name: JBenson)" | |
echo "Username and password will match" | |
read -r USER_NAME | |
openstack project create $USER_NAME | |
openstack user create --project $USER_NAME --password $USER_NAME $USER_NAME | |
openstack role add --project $USER_NAME --user $USER_NAME _member_ | |
} | |
function create_local_networking () { | |
tenant=$(choice_option "$( (project_list) )") | |
openstack network create --project "${tenant}" private | |
openstack subnet create --project "${tenant}" --subnet-range 192.168.100.0/24 --dns-nameserver "${MYDNS}" --network private private_subnet | |
openstack router create --enable --project "${tenant}" pub-router | |
openstack router set pub-router --external-gateway public | |
openstack router add subnet pub-router private_subnet | |
} | |
function update_security_groups () { | |
myProject=$(choice_option "$( (project_list) )") | |
default_group=$(openstack security group list --project $myProject -f value -c ID) | |
echo "Installing SSH rule..." | |
openstack security group rule create --project $myProject --protocol tcp --dst-port 22:22 --remote-ip 0.0.0.0/0 "${default_group}" | |
echo "Installing HTTP rule..." | |
openstack security group rule create --project $myProject --protocol tcp --dst-port 80:80 --remote-ip 0.0.0.0/0 "${default_group}" | |
echo "Installing HTTPS rule..." | |
openstack security group rule create --project $myProject --protocol tcp --dst-port 443:443 --remote-ip 0.0.0.0/0 "${default_group}" | |
echo "Installing ICMP rule..." | |
openstack security group rule create --project $myProject --protocol icmp "${default_group}" | |
} | |
function find_compute_servers () { | |
compute=($(openstack compute service list -f value -c Host --service nova-compute)) | |
echo "${compute[@]}" | |
} | |
function deploy_instance () { | |
echo "Deploying a single instance ..." | |
echo "" | |
echo "Please choose your base OS" | |
myOS=$(choice_option "$( (read_image) )") | |
echo "Please choose your base VM size" | |
myFlavors=$(choice_option "$( (read_flavors) )") | |
KEYPAIR_LIST=($(openstack keypair list -c Name -f value)) | |
echo "Please choose the network to deploy on:" | |
myNetwork=$(choice_option "$( (read_networks) )") | |
if [[ ! " ${KEYPAIR_LIST[@]} " =~ " $KEYPAIR_NAME " ]]; then | |
echo "Creating the keypair" | |
openstack keypair create --private-key $KEYPAIR_NAME $KEYPAIR_NAME | |
chmod 600 ~/$KEYPAIR_NAME | |
fi | |
openstack server create --key-name $KEYPAIR_NAME --network $myNetwork --image $myOS --flavor $myFlavors $INSTANCE_NAME | |
FLOATING_IP=$(openstack floating ip create "$( (read_admin_networking) )" -f value -c floating_ip_address) | |
echo "Assigning public IP to server: $FLOATING_IP" | |
openstack server add floating ip $INSTANCE_NAME $FLOATING_IP | |
while true ; do | |
STATUS_STATE=$(openstack server list -c Status --name $INSTANCE_NAME -f value) | |
STATUS_VALUE=$( check_status $STATUS_STATE ) | |
VALUE="${STATUS_VALUE: -1}" | |
echo $STATUS_VALUE | |
case $VALUE in | |
1 ) exit 1;; | |
2 ) break;; | |
3 ) sleep 1;; | |
* ) echo "Unknown" | |
esac | |
sleep 1 | |
done | |
if [[ $myOS == *"buntu"* ]]; then MYCMD="ssh -i ~/$KEYPAIR_NAME ubuntu@$FLOATING_IP" ; fi | |
if [[ $myOS == *"ent"* ]]; then MYCMD="ssh -i ~/$KEYPAIR_NAME centos@$FLOATING_IP" ; fi | |
if [[ $myOS == *"irr"* ]]; then MYCMD="ssh -i ~/$KEYPAIR_NAME cirros@$FLOATING_IP" ; fi | |
echo "###########################################" | |
echo "Please verify connectivity:" | |
echo "$MYCMD" | |
echo "###########################################" | |
# sleep 2 | |
# eval "$MYCMD" | |
} | |
function deploy_VM_on_all_compute_nodes () { | |
echo "Deploying a VM on all compute nodes" | |
echo " The selections used below will be used on all VM's created" | |
echo " Upon successful creation, the VM's will be automatically deleted." | |
echo "" | |
myOS=$(choice_option "$( (read_image) )") | |
myFlavors=$(choice_option "$( (read_flavors) )") | |
KEYPAIR_LIST=($(openstack keypair list -c Name -f value)) | |
myNetwork=$(choice_option "$( (read_networks) )") | |
servers="$( (find_compute_servers) )" | |
if [[ ! " ${KEYPAIR_LIST[@]} " =~ " $KEYPAIR_NAME " ]]; then | |
echo "Creating the keypair" | |
openstack keypair create --private-key $KEYPAIR_NAME $KEYPAIR_NAME | |
chmod 600 ~/$KEYPAIR_NAME | |
fi | |
for i in $servers; do | |
echo "Deploying server on $i" | |
openstack server create --key-name $KEYPAIR_NAME --network $myNetwork --image $myOS --flavor $myFlavors --availability-zone nova::$i $INSTANCE_NAME | |
while true ; do | |
STATUS_STATE=$(openstack server list -c Status --name $INSTANCE_NAME -f value) | |
STATUS_VALUE=$( check_status $STATUS_STATE ) | |
VALUE="${STATUS_VALUE: -1}" | |
echo $STATUS_VALUE | |
case $VALUE in | |
1 ) exit 1;; | |
2 ) echo " Deleting server $INSTANCE_NAME" | |
openstack server delete $INSTANCE_NAME | |
echo " Delete complete" | |
break;; | |
3 ) sleep 1;; | |
* ) echo "Unkown" | |
esac | |
sleep 1 | |
done | |
done | |
} | |
function check_status () { | |
SOURCE=$1 | |
LIST_OF_BAD_STATUS="down failed error :-(" | |
LIST_OF_GOOD_STATUS="active running :-)" | |
if echo "$LIST_OF_BAD_STATUS" | grep -i -q "$SOURCE"; then | |
echo "This is a bad state: $SOURCE"; | |
echo "1" | |
elif echo "$LIST_OF_GOOD_STATUS" | grep -i -q "$SOURCE"; then | |
echo "Operation is complete, now $SOURCE." | |
echo "2" | |
else | |
echo "Operation ($SOURCE) still proceeding. Please wait."; | |
echo "3" | |
fi | |
} | |
function snapshot_restore_deploy () { | |
echo "Creating a snapshot...." | |
if [[ -z "$INSTANCE_NAME" ]]; then | |
INSTANCE_NAME=$(choice_option "$( (read_instances) )") | |
fi | |
SNAP_INSTANCE_NAME=$INSTANCE_NAME"_SNAPSHOT" | |
RESTORED_NAME=$INSTANCE_NAME"-restored" | |
DEPLOYED_RESTORED_IMAGE="FINAL_RESTORE" | |
FLAVOR_SIZE=$(openstack server list --long --name $INSTANCE_NAME -f value -c 'Flavor Name') | |
echo "Creating Snapshot [$SNAP_INSTANCE_NAME], please wait" | |
IMAGE_ID=$(openstack server image create --name $SNAP_INSTANCE_NAME -f value -c id $INSTANCE_NAME) | |
while true ; do | |
mySTATUS=$(openstack image list --name $SNAP_INSTANCE_NAME -f value -c Status) | |
echo "[$mySTATUS]" | |
if [[ $mySTATUS == *"active"* ]]; then break ; fi | |
sleep 5 | |
done | |
echo "Snapshot complete, downloading snapshot..." | |
mySNAPSize=$(openstack image list --name $SNAP_INSTANCE_NAME --long -f value -c Size) | |
echo $mySNAPSize | |
openstack image save --file $SNAP_INSTANCE_NAME.raw $SNAP_INSTANCE_NAME & | |
while true ; do | |
myDLSnapSize=$(stat --printf="%s" $SNAP_INSTANCE_NAME.raw) | |
echo $myDLSnapSize | |
if [[ $mySNAPSize == $myDLSnapSize ]]; then break ; fi | |
echo "Downloading..." | |
sleep 5 | |
done | |
echo "Download complete, restoring image" | |
sleep 5 | |
openstack image create --container-format bare --disk-format qcow2 --file $SNAP_INSTANCE_NAME.raw $RESTORED_NAME & | |
while true ; do | |
mySTATUS=$(openstack image list --name $RESTORED_NAME -f value -c Status) | |
echo $mySTATUS | |
if [[ $mySTATUS == *"active"* ]]; then break ; fi | |
sleep 5 | |
done | |
echo "Image successfully restored." | |
echo "Deploying restored image." | |
openstack server create --image $RESTORED_NAME --flavor $FLAVOR_SIZE $DEPLOYED_RESTORED_IMAGE | |
while true ; do | |
mySTATUS=$(openstack server list --name $DEPLOYED_RESTORED_IMAGE -f value -c Status) | |
echo $mySTATUS | |
if [[ $mySTATUS == *"active"* ]]; then break ; fi | |
sleep 5 | |
done | |
echo "Deploy from restored image sucessful." | |
} | |
function create_volume () { | |
instances="$( (read_instances) )" | |
if [ -z $instances ]; then | |
echo "No instances, deploying new instance" | |
"$( (deploy_instance) )" | |
INSTANCE_NAME="$( (read_instances) )" | |
else | |
echo "Please choose an instance to attach the volume to:" | |
INSTANCE_NAME=$(choice_option $instances) | |
fi | |
echo "Creating volume..." | |
openstack volume create --size $VOLUME_SIZE $VOLUME_NAME | |
VOLUME_ID=$(openstack volume list -f value -c ID --name $VOLUME_NAME) | |
while true ; do | |
mySTATUS=$(openstack volume show $VOLUME_ID -f value -c status) | |
echo "Status: $mySTATUS" | |
if [[ $mySTATUS == *"available"* ]]; then break ; fi | |
sleep 2 | |
done | |
echo "Attaching volume..." | |
openstack server add volume --device /dev/vdb $INSTANCE_NAME $VOLUME_ID | |
while true ; do | |
mySTATUS=$(openstack volume show $VOLUME_ID -f value -c attachments) | |
if ! [[ $mySTATUS == *"[]"* ]]; then break ; fi | |
sleep 2 | |
done | |
echo "Volume attached." | |
ATTACHMENT_INFO=$(openstack volume show $VOLUME_ID -f value -c attachments) | |
ATTACHMENT_STATUS=$(openstack volume show $VOLUME_ID -f value -c status) | |
echo "Attachment status: $ATTACHMENT_STATUS" | |
echo "Attachment info: $ATTACHMENT_INFO" | |
echo "Detaching volume from instance..." | |
openstack server remove volume $INSTANCE_NAME $VOLUME_ID | |
while true ; do | |
mySTATUS=$(openstack volume show $VOLUME_ID -f value -c attachments) | |
if [[ $mySTATUS == *"[]"* ]]; then break ; fi | |
sleep 2 | |
done | |
echo "Volume detached." | |
echo "Resizing volume from $VOLUME_SIZE to $NEW_VOLUME_SIZE..." | |
openstack volume set $VOLUME_ID --size $NEW_VOLUME_SIZE | |
while true ; do | |
mySTATUS=$(openstack volume show $VOLUME_ID -f value -c size) | |
echo "Current Volume size: $mySTATUS" | |
if [[ $mySTATUS == $NEW_VOLUME_SIZE ]]; then break ; fi | |
sleep 5 | |
done | |
echo "Resize complete." | |
echo "Deleting volume..." | |
openstack volume delete $VOLUME_NAME | |
echo "Delete complete." | |
} | |
function usage () { | |
echo "" | |
echo " Setup openstack" | |
echo "" | |
echo "Missing paramter. Please Enter one of the following options" | |
echo "" | |
echo "Usage: $0 {Any of the options below}" | |
echo "" | |
echo "" | |
echo " one_time" | |
echo " Install python-openstackclient locally (--user)" | |
echo "" | |
echo " read_image" | |
echo " See what images are installed" | |
echo " " | |
echo " create_image" | |
echo " Choose to download and install centos, ubuntu, cirros." | |
echo " will also verify if the OS is already installed." | |
echo "" | |
echo " create_flavors" | |
echo " This will create a tiny, small, medium, large, xlarge" | |
echo " " | |
echo " read_flavors" | |
echo " See what flavors exist, able to filter by name" | |
echo "" | |
echo " update_security_groups" | |
echo " Install SSH, HTTP, HTTPS, ICMP security group rule" | |
echo " " | |
echo " create_admin_networking" | |
echo " Creates public external admin network" | |
echo "" | |
echo " read_admin_networking" | |
echo " Get the admin network ID" | |
echo "" | |
echo " create_local_networking" | |
echo " Create local networking for project." | |
echo "" | |
echo " deploy_instance" | |
echo " Choice an OS & flavor, create a keypair if necessary, assign " | |
echo " a floating IP, and SSH into it." | |
echo "" | |
echo " deploy_VM_on_all_compute_nodes" | |
echo " Deploy VM's on all compute nodes, if successful, VM's will be deleted." | |
echo "" | |
echo " read_instances" | |
echo " Get list of instances" | |
echo "" | |
echo " project_list" | |
echo " Get list of projects" | |
echo "" | |
echo " create_volume" | |
echo " Create a volume, attach volume to instance, detach volume from instance" | |
echo " resize volume, delete volume." | |
echo "" | |
echo " snapshot_restore_deploy" | |
echo " Snapshot an image, download it, upload it, deploy new snapshot." | |
echo "" | |
echo " create_group_user" | |
echo " Create a new user/project and join user to it." | |
} | |
function main () { | |
echo "" | |
echo "" | |
echo "" | |
if [ -z "$1" ]; then | |
usage | |
exit 1 | |
fi | |
if [ "$1" == "deploy_all" ]; then | |
echo "" | |
else | |
case $1 in | |
"one_time") | |
one_time;; | |
"read_image") | |
read_image;; | |
"create_image") | |
create_image;; | |
"create_flavors") | |
create_flavors;; | |
"read_flavors") | |
read_flavors;; | |
"update_security_groups") | |
update_security_groups;; | |
"create_admin_networking") | |
create_admin_networking;; | |
"read_admin_networking") | |
read_admin_networking;; | |
"create_local_networking") | |
create_local_networking;; | |
"deploy_instance") | |
deploy_instance;; | |
"read_instances") | |
read_instances;; | |
"create_group_user") | |
create_group_user;; | |
"project_list") | |
project_list;; | |
"create_networking") | |
create_networking;; | |
"snapshot_restore_deploy") | |
snapshot_restore_deploy;; | |
"create_volume") | |
create_volume;; | |
"deploy_VM_on_all_compute_nodes") | |
deploy_VM_on_all_compute_nodes;; | |
"temp") | |
temp;; | |
esac | |
fi | |
} | |
main "$1" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated flavor sizes.