Docker Development

Adding docker integration for easy development of quark.  This
will be closely tied to the current software revision on any
given patch.  This allows you to vagrant up any current code
revision as it will copy over the current working codebase to the
docker image for installation into a virtualenv.

This also employs several docker containers to make it easier to
manage.  It contains Redis, RabbitMQ, MySQL, PHPMySQLAdmin,
and Kabana with Elasticsearch for log analysis.

If your code changes and you need to test again after you
docker_up.sh, you can easily docker_reload.sh and it will
only update quark and start the process.  In addition,
this will insert a set number of networks and subnets for
easy starting.

Change-Id: I70d0ec9aed1548796bd8d4a9c1a94506234378f9
JIRA:NCP-1692
Implements: blueprint vagrant-quark
This commit is contained in:
Brian Stajkowski 2016-06-23 21:20:32 -07:00
parent ed5efb730a
commit ba31915a50
9 changed files with 550 additions and 0 deletions

3
.gitignore vendored
View File

@ -49,3 +49,6 @@ ChangeLog
# Docs
docs/build
# Vagrant
.vagrant/

View File

@ -101,3 +101,57 @@ and detail as much of the requirement as possible.
We will review and determine if it is possible and when a developer can be
assigned to the request.
DOCKER DEVELOPMENT ENVIRONMENT
==============================
Quick Start
-----------
1. Install Docker: https://docs.docker.com/engine/installation/
2. cd <quark_repo_dir>
3. ./docker_up.sh
4. First time? Please wait to download the containers.
5. This will install the code currently in the directory.
6. If you need to update the development environment with code you have changed,
just ./docker_reload.sh once you have the environment up. This will reload the
quark container with your new code.
7. Have your own configs? Not a problem, just create a ~/neutron directory local
on your laptop or working environment. The default configs will be overwritten
by your configuration files. They will also be loaded fresh everytime with
./docker_reload.sh.
8. By default if a configuration file is not in ~/netron directory, it will load
docker.neutron.conf, docker.apipaste.ini, and docker.policy.json in this repo.
9. Once you are done with the evironment, just ./docker_down.sh
10. What's in the Dev Environment?
- ELK Stack(logging): http://localhost:8083
- PHPMyAdmin: http://localhost:8081
- Neutron/Quark: http://localhost:9696
- RabbitMQ: http://localhost:8080
- Redis-Master: 80
- Redis-Sentinel: 6380
- MySQL: 3306
For addiitonal ports, please see the docker_up.sh script.
11. Need to reference the IP of one of the containers? No need, the quark
container handles the linking and generating /etc/hosts with the correct
IPs. To access any of the containers in your configurations files, use the
following hostnames:
- ELK: docker-kibana
- MySQL: docker-mysql
- RabbitMQ: docker-rabbitmq
- Redis: docker-redis
- Redis-Sentinel: docker-redis-sentinel

56
Dockerfile Normal file
View File

@ -0,0 +1,56 @@
FROM ubuntu:14.04
# General Installation
RUN apt-get update && apt-get install -y python-pip python-dev git wget libmysqlclient-dev build-essential libssl-dev libffi-dev python-dev rsyslog mysql-client
RUN pip install virtualenv
# Configure Rsyslog and Provision DB
RUN echo 'local0.* @@docker-kibana:514' > /etc/rsyslog.d/60-neutron.conf
RUN echo "service rsyslog restart" > ~/entrypoint.sh
RUN echo 'mysql -h docker-mysql -u root -ppassword -e "CREATE DATABASE neutron"' >> ~/entrypoint.sh
# Update setuptools
RUN wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo python
# Make our directories
RUN mkdir /opt/configs /opt/neutron /opt/quark /opt/venv /opt/wafflehaus /opt/wafflehaus.neutron /var/log/neutron
RUN cd /opt/venv && virtualenv . --distribute
# Clone Neutron & Wafflehaus
RUN git clone https://github.com/openstack/neutron /opt/neutron
RUN git clone https://github.com/roaet/wafflehaus.git /opt/wafflehaus
RUN git clone https://github.com/roaet/wafflehaus.neutron /opt/wafflehaus.neutron
# Pull Neutron and Install
RUN echo "cd /opt/neutron && git pull" >> ~/entrypoint.sh
RUN echo "source /opt/venv/bin/activate && pip install -U -r /opt/neutron/requirements.txt" >> ~/entrypoint.sh
RUN echo "cd /opt/neutron && source /opt/venv/bin/activate && python setup.py develop" >> ~/entrypoint.sh
# Install Quark
RUN echo "source /opt/venv/bin/activate && pip install -U -r /opt/quark/requirements.txt" >> ~/entrypoint.sh
RUN echo "cd /opt/quark && source /opt/venv/bin/activate && python setup.py develop" >> ~/entrypoint.sh
# Install Wafflehaus
RUN echo "cd /opt/wafflehaus && git pull" >> ~/entrypoint.sh
RUN echo "source /opt/venv/bin/activate && pip install -U -r /opt/wafflehaus/requirements.txt" >> ~/entrypoint.sh
RUN echo "cd /opt/wafflehaus && source /opt/venv/bin/activate && python setup.py develop" >> ~/entrypoint.sh
# Install Wafflehaus.Neutron
RUN echo "cd /opt/wafflehaus.neutron && git pull" >> ~/entrypoint.sh
RUN echo "source /opt/venv/bin/activate && pip install -U -r /opt/wafflehaus.neutron/requirements.txt" >> ~/entrypoint.sh
RUN echo "cd /opt/wafflehaus.neutron && source /opt/venv/bin/activate && python setup.py develop" >> ~/entrypoint.sh
# Put configuration files in place and start Neutron
RUN echo "cp /opt/quark/docker.neutron.conf ~/neutron.conf" >> ~/entrypoint.sh
RUN echo "cp /opt/quark/docker.apipaste.ini ~/api-paste.ini" >> ~/entrypoint.sh
RUN echo "cp /opt/quark/docker.policy.json ~/policy.json" >> ~/entrypoint.sh
RUN echo "cp /opt/configs/* ~/" >> ~/entrypoint.sh
RUN echo "source /opt/venv/bin/activate && quark-db-manage --config-file ~/neutron.conf upgrade head" >> ~/entrypoint.sh
RUN echo "source /opt/venv/bin/activate && neutron-server --config-file ~/neutron.conf" >> ~/entrypoint.sh
RUN chmod +x ~/entrypoint.sh
EXPOSE 9696
ENTRYPOINT ["/bin/bash", "-c", "~/entrypoint.sh"]

34
docker.apipaste.ini Normal file
View File

@ -0,0 +1,34 @@
[composite:neutron]
use = egg:Paste#urlmap
/: neutronversions
/v2.0: neutronapi_v2_0
[composite:neutronapi_v2_0]
use = call:neutron.auth:pipeline_factory
noauth = cors request_id catch_errors extensions neutronapiapp_v2_0
keystone = cors request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0
[filter:request_id]
paste.filter_factory = oslo_middleware:RequestId.factory
[filter:catch_errors]
paste.filter_factory = oslo_middleware:CatchErrors.factory
[filter:cors]
paste.filter_factory = oslo_middleware.cors:filter_factory
oslo_config_project = neutron
[filter:keystonecontext]
paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
[filter:extensions]
paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory
[app:neutronversions]
paste.app_factory = neutron.api.versions:Versions.factory
[app:neutronapiapp_v2_0]
paste.app_factory = neutron.api.v2.router:APIRouter.factory

34
docker.neutron.conf Normal file
View File

@ -0,0 +1,34 @@
[DEFAULT]
lock_path = $state_path/lock
core_plugin = quark.plugin.Plugin
auth_strategy = noauth
fake_rabbit = false
rpc_backend = rabbit
log_dir: "/var/log/neutron"
use_syslog: "True"
syslog_log_facility: "LOG_LOCAL0"
[DATABASE]
connection = mysql://root:password@docker-mysql/neutron?charset=utf8
reconnect_interval = 5
auto_create_schema = False
min_pool_size = 100
max_pool_size = 500
max_overflow = 500
[QUARK]
public_net_id=00000000-0000-0000-0000-000000000000
net_driver=quark.drivers.unmanaged.UnmanagedDriver
default_net_strategy='{"00000000-0000-0000-0000-000000000000": {"bridge": "publicnet"}, "11111111-1111-1111-1111-111111111111": {"bridge": "servicenet"}}'
default_network_type=UNMANAGED
# IPAM recycling interval, in seconds
ipam_reuse_after= 300
ipam_retry=1
show_subnet_ip_policy_id = False
show_allocation_pools = True
pessimistic_connection_pooling = True
environment_capabilities = ""
[oslo_messaging_notifications]
driver = messaging
transport_url = 'rabbit://admin:password@docker-rabbitmq:5672/'

222
docker.policy.json Normal file
View File

@ -0,0 +1,222 @@
{
"context_is_admin": "role:admin",
"owner": "tenant_id:%(tenant_id)s",
"admin_or_owner": "rule:context_is_admin or rule:owner",
"context_is_advsvc": "role:advsvc",
"admin_or_network_owner": "rule:context_is_admin or tenant_id:%(network:tenant_id)s",
"admin_owner_or_network_owner": "rule:owner or rule:admin_or_network_owner",
"admin_only": "rule:context_is_admin",
"regular_user": "",
"shared": "field:networks:shared=True",
"shared_firewalls": "field:firewalls:shared=True",
"shared_firewall_policies": "field:firewall_policies:shared=True",
"shared_subnetpools": "field:subnetpools:shared=True",
"shared_address_scopes": "field:address_scopes:shared=True",
"external": "field:networks:router:external=True",
"default": "rule:admin_or_owner",
"create_subnet": "rule:admin_or_network_owner",
"create_subnet:segment_id": "rule:admin_only",
"get_subnet": "rule:admin_or_owner or rule:shared",
"get_subnet:segment_id": "rule:admin_only",
"update_subnet": "rule:admin_or_network_owner",
"delete_subnet": "rule:admin_or_network_owner",
"create_subnetpool": "",
"create_subnetpool:shared": "rule:admin_only",
"create_subnetpool:is_default": "rule:admin_only",
"get_subnetpool": "rule:admin_or_owner or rule:shared_subnetpools",
"update_subnetpool": "rule:admin_or_owner",
"update_subnetpool:is_default": "rule:admin_only",
"delete_subnetpool": "rule:admin_or_owner",
"create_address_scope": "",
"create_address_scope:shared": "rule:admin_only",
"get_address_scope": "rule:admin_or_owner or rule:shared_address_scopes",
"update_address_scope": "rule:admin_or_owner",
"update_address_scope:shared": "rule:admin_only",
"delete_address_scope": "rule:admin_or_owner",
"create_network": "",
"get_network": "rule:admin_or_owner or rule:shared or rule:external or rule:context_is_advsvc",
"get_network:router:external": "rule:regular_user",
"get_network:segments": "rule:admin_only",
"get_network:provider:network_type": "rule:admin_only",
"get_network:provider:physical_network": "rule:admin_only",
"get_network:provider:segmentation_id": "rule:admin_only",
"get_network:queue_id": "rule:admin_only",
"get_network_ip_availabilities": "rule:admin_only",
"get_network_ip_availability": "rule:admin_only",
"create_network:shared": "rule:admin_only",
"create_network:router:external": "rule:admin_only",
"create_network:is_default": "rule:admin_only",
"create_network:segments": "rule:admin_only",
"create_network:provider:network_type": "rule:admin_only",
"create_network:provider:physical_network": "rule:admin_only",
"create_network:provider:segmentation_id": "rule:admin_only",
"update_network": "rule:admin_or_owner",
"update_network:segments": "rule:admin_only",
"update_network:shared": "rule:admin_only",
"update_network:provider:network_type": "rule:admin_only",
"update_network:provider:physical_network": "rule:admin_only",
"update_network:provider:segmentation_id": "rule:admin_only",
"update_network:router:external": "rule:admin_only",
"delete_network": "rule:admin_or_owner",
"create_segment": "rule:admin_only",
"get_segment": "rule:admin_only",
"update_segment": "rule:admin_only",
"delete_segment": "rule:admin_only",
"network_device": "field:port:device_owner=~^network:",
"create_port": "",
"create_port:device_owner": "not rule:network_device or rule:context_is_advsvc or rule:admin_or_network_owner",
"create_port:mac_address": "rule:context_is_advsvc or rule:admin_or_network_owner",
"create_port:fixed_ips": "rule:context_is_advsvc or rule:admin_or_network_owner",
"create_port:port_security_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
"create_port:binding:host_id": "rule:admin_only",
"create_port:binding:profile": "rule:admin_only",
"create_port:mac_learning_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
"create_port:allowed_address_pairs": "rule:admin_or_network_owner",
"get_port": "rule:context_is_advsvc or rule:admin_owner_or_network_owner",
"get_port:queue_id": "rule:admin_only",
"get_port:binding:vif_type": "rule:admin_only",
"get_port:binding:vif_details": "rule:admin_only",
"get_port:binding:host_id": "rule:admin_only",
"get_port:binding:profile": "rule:admin_only",
"update_port": "rule:admin_or_owner or rule:context_is_advsvc",
"update_port:device_owner": "not rule:network_device or rule:context_is_advsvc or rule:admin_or_network_owner",
"update_port:mac_address": "rule:admin_only or rule:context_is_advsvc",
"update_port:fixed_ips": "rule:context_is_advsvc or rule:admin_or_network_owner",
"update_port:port_security_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
"update_port:binding:host_id": "rule:admin_only",
"update_port:binding:profile": "rule:admin_only",
"update_port:mac_learning_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
"update_port:allowed_address_pairs": "rule:admin_or_network_owner",
"delete_port": "rule:context_is_advsvc or rule:admin_owner_or_network_owner",
"get_router:ha": "rule:admin_only",
"create_router": "rule:regular_user",
"create_router:external_gateway_info:enable_snat": "rule:admin_only",
"create_router:distributed": "rule:admin_only",
"create_router:ha": "rule:admin_only",
"get_router": "rule:admin_or_owner",
"get_router:distributed": "rule:admin_only",
"update_router:external_gateway_info:enable_snat": "rule:admin_only",
"update_router:distributed": "rule:admin_only",
"update_router:ha": "rule:admin_only",
"delete_router": "rule:admin_or_owner",
"add_router_interface": "rule:admin_or_owner",
"remove_router_interface": "rule:admin_or_owner",
"create_router:external_gateway_info:external_fixed_ips": "rule:admin_only",
"update_router:external_gateway_info:external_fixed_ips": "rule:admin_only",
"create_firewall": "",
"get_firewall": "rule:admin_or_owner",
"create_firewall:shared": "rule:admin_only",
"get_firewall:shared": "rule:admin_only",
"update_firewall": "rule:admin_or_owner",
"update_firewall:shared": "rule:admin_only",
"delete_firewall": "rule:admin_or_owner",
"create_firewall_policy": "",
"get_firewall_policy": "rule:admin_or_owner or rule:shared_firewall_policies",
"create_firewall_policy:shared": "rule:admin_or_owner",
"update_firewall_policy": "rule:admin_or_owner",
"delete_firewall_policy": "rule:admin_or_owner",
"insert_rule": "rule:admin_or_owner",
"remove_rule": "rule:admin_or_owner",
"create_firewall_rule": "",
"get_firewall_rule": "rule:admin_or_owner or rule:shared_firewalls",
"update_firewall_rule": "rule:admin_or_owner",
"delete_firewall_rule": "rule:admin_or_owner",
"create_qos_queue": "rule:admin_only",
"get_qos_queue": "rule:admin_only",
"update_agent": "rule:admin_only",
"delete_agent": "rule:admin_only",
"get_agent": "rule:admin_only",
"create_dhcp-network": "rule:admin_only",
"delete_dhcp-network": "rule:admin_only",
"get_dhcp-networks": "rule:admin_only",
"create_l3-router": "rule:admin_only",
"delete_l3-router": "rule:admin_only",
"get_l3-routers": "rule:admin_only",
"get_dhcp-agents": "rule:admin_only",
"get_l3-agents": "rule:admin_only",
"get_loadbalancer-agent": "rule:admin_only",
"get_loadbalancer-pools": "rule:admin_only",
"get_agent-loadbalancers": "rule:admin_only",
"get_loadbalancer-hosting-agent": "rule:admin_only",
"create_floatingip": "rule:regular_user",
"create_floatingip:floating_ip_address": "rule:admin_only",
"update_floatingip": "rule:admin_or_owner",
"delete_floatingip": "rule:admin_or_owner",
"get_floatingip": "rule:admin_or_owner",
"create_network_profile": "rule:admin_only",
"update_network_profile": "rule:admin_only",
"delete_network_profile": "rule:admin_only",
"get_network_profiles": "",
"get_network_profile": "",
"update_policy_profiles": "rule:admin_only",
"get_policy_profiles": "",
"get_policy_profile": "",
"create_metering_label": "rule:admin_only",
"delete_metering_label": "rule:admin_only",
"get_metering_label": "rule:admin_only",
"create_metering_label_rule": "rule:admin_only",
"delete_metering_label_rule": "rule:admin_only",
"get_metering_label_rule": "rule:admin_only",
"get_service_provider": "rule:regular_user",
"get_lsn": "rule:admin_only",
"create_lsn": "rule:admin_only",
"create_flavor": "rule:admin_only",
"update_flavor": "rule:admin_only",
"delete_flavor": "rule:admin_only",
"get_flavors": "rule:regular_user",
"get_flavor": "rule:regular_user",
"create_service_profile": "rule:admin_only",
"update_service_profile": "rule:admin_only",
"delete_service_profile": "rule:admin_only",
"get_service_profiles": "rule:admin_only",
"get_service_profile": "rule:admin_only",
"get_policy": "rule:regular_user",
"create_policy": "rule:admin_only",
"update_policy": "rule:admin_only",
"delete_policy": "rule:admin_only",
"get_policy_bandwidth_limit_rule": "rule:regular_user",
"create_policy_bandwidth_limit_rule": "rule:admin_only",
"delete_policy_bandwidth_limit_rule": "rule:admin_only",
"update_policy_bandwidth_limit_rule": "rule:admin_only",
"get_policy_dscp_marking_rule": "rule:regular_user",
"create_policy_dscp_marking_rule": "rule:admin_only",
"delete_policy_dscp_marking_rule": "rule:admin_only",
"update_policy_dscp_marking_rule": "rule:admin_only",
"get_rule_type": "rule:regular_user",
"restrict_wildcard": "(not field:rbac_policy:target_tenant=*) or rule:admin_only",
"create_rbac_policy": "",
"create_rbac_policy:target_tenant": "rule:restrict_wildcard",
"update_rbac_policy": "rule:admin_or_owner",
"update_rbac_policy:target_tenant": "rule:restrict_wildcard and rule:admin_or_owner",
"get_rbac_policy": "rule:admin_or_owner",
"delete_rbac_policy": "rule:admin_or_owner",
"create_flavor_service_profile": "rule:admin_only",
"delete_flavor_service_profile": "rule:admin_only",
"get_flavor_service_profile": "rule:regular_user",
"get_auto_allocated_topology": "rule:admin_or_owner"
}

50
docker_down.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/bash
echo "Mysql: Stopping & Deleting Container..."
docker stop mysql
docker rm mysql
echo "Mysql: Complete"
echo "-----------------------"
echo " "
echo "PHPMyAdmin: Stopping & Deleting Container..."
docker stop phpmyadmin
docker rm phpmyadmin
echo "PHPMyAdmin: Complete"
echo "-----------------------"
echo " "
echo "ELK: Stopping & Deleting Container..."
docker stop kibana
docker rm kibana
echo "ELK: Complete"
echo "-----------------------"
echo " "
echo "RabbitMQ: Stopping & Deleting Container..."
docker stop rabbitmq
docker rm rabbitmq
echo "RabbitMQ: Complete"
echo "-----------------------"
echo " "
echo "Redis: Stopping & Deleting Container..."
docker stop redis
docker rm redis
echo "Redis: Complete"
echo "-----------------------"
echo " "
echo "Redis Sentinel: Stopping & Deleting Container..."
docker stop redis-sentinel
docker rm redis-sentinel
echo "Redis Sentinel: Complete"
echo "-----------------------"
echo " "
echo "Neutron/Quark: Stopping & Deleting Container..."
docker stop quark
docker rm quark
echo "Neutron/Quark: Complete"
echo "-----------------------"
echo " "

12
docker_reload.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
echo "Neutron/Quark: Stopping & Deleting Container..."
docker stop quark
docker rm quark
echo "Neutron/Quark: Complete"
echo "-----------------------"
echo " "
echo "Neutron/Quark: Starting Container..."
docker run -d -v $(pwd):/opt/quark -v ~/neutron:/opt/configs -p 9696:9696 --link mysql:docker-mysql --link kibana:docker-kibana --link rabbitmq:docker-rabbitmq --link redis-sentinel:docker-redis-sentinel --name quark stajkowski/quark
echo "Neutron/Quark - Complete - http://localhost:9696"

85
docker_up.sh Executable file
View File

@ -0,0 +1,85 @@
#!/bin/bash
# To build a new container
# docker build -t quark .
echo "Mysql: Starting Container..."
docker run -d --restart=always -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=password -d mysql
echo "Mysql: Waiting for Mysql to Start..."
# Need to wait for DB to standup
sleep 30
echo "Mysql: Complete - PORT 3306"
echo "------------------------------------------"
echo " "
echo "PHPMyAdmin: Starting Container..."
docker run -d --restart=always --name phpmyadmin --link mysql:mysql -p 8081:80 nazarpc/phpmyadmin
echo "PHPMyAdmin: Complete - http://localhost:8081"
echo "------------------------------------------"
echo " "
echo "ELK: Starting Container..."
docker run --restart=always --name kibana -d -p 514:514 -p 514:514/udp -p 8083:5601 -v /etc/localtime:/etc/localtime:ro pschiffe/rsyslog-elasticsearch-kibana
echo "ELK: Complete - http://localhost:8083"
echo "------------------------------------------"
echo " "
echo "RabbitMQ: Starting Container..."
docker run -d --restart=always --hostname baserabbitmq -p 8080:15672 -p 5671-5672:5671-5672 -p 15671:15671 -p 4369:4369 -p 25672:25672 --name rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=password -e RABBITMQ_ERLANG_COOKIE='w9efn934ht34t3' rabbitmq:3-management
echo "RabbitMQ: Complete - http://localhost:8080"
echo "------------------------------------------"
echo " "
echo "Redis: Starting Master Container..."
docker run -d --restart=always -p 80:80 -v ~/data/redis0:/data --name=redis stajkowski/redis-master
echo "Redis: Complete - PORT 80"
echo "------------------------------------------"
echo " "
echo "Redis Sentinel: Starting Sentinel Container..."
docker run -d --restart=always -p 6380:6380 -v ~/data/redis0:/data --link redis:docker-redis --name=redis-sentinel stajkowski/redis-sentinel
echo "Redis Sentinel: Complete - PORT 6380"
echo "------------------------------------------"
echo " "
echo "Neutron/Quark: Starting Container..."
docker run -d -v $(pwd):/opt/quark -v ~/neutron:/opt/configs -p 9696:9696 --link mysql:docker-mysql --link kibana:docker-kibana --link rabbitmq:docker-rabbitmq --link redis-sentinel:docker-redis-sentinel --name quark stajkowski/quark
# docker run --entrypoint /bin/bash -v $(pwd):/opt/quark -v ~/neutron:/opt/configs -p 9696:9696 --link mysql:docker-mysql --link kibana:docker-kibana --link rabbitmq:docker-rabbitmq --link redis-sentinel:docker-redis-sentinel --name quark stajkowski/quark
echo "Neutron/Quark: Waiting for Neutron to Start..."
# Need to wait for DB to standup
sleep 180
echo "Neutron/Quark: Complete - http://localhost:9696"
echo "------------------------------------------"
echo " "
echo "Creating Networks..."
echo "------------------------------------------"
echo "Creating Mac Range..."
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"mac_address_range": {"cidr" : "AA:BB:CC", "tenant_id": "provider"}}' http://localhost:9696/v2.0/mac_address_ranges.json
echo " "
echo "Creating Network..."
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"network": {"id": "00000000-0000-0000-0000-000000000000", "tenant_id": "provider", "name": "public"}}' http://localhost:9696/v2.0/networks
echo " "
echo "Creating Subnets..."
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"subnet": {"network_id": "00000000-0000-0000-0000-000000000000", "segment_id": "blah", "cidr": "10.1.0.0/16", "tenant_id": "derp", "ip_version": "4"}}' http://localhost:9696/v2.0/subnets
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"subnet": {"network_id": "00000000-0000-0000-0000-000000000000", "segment_id": "blah", "cidr": "10.2.0.0/16", "tenant_id": "derp", "ip_version": "4"}}' http://localhost:9696/v2.0/subnets
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"subnet": {"network_id": "00000000-0000-0000-0000-000000000000", "segment_id": "blah", "cidr": "10.3.0.0/16", "tenant_id": "derp", "ip_version": "4"}}' http://localhost:9696/v2.0/subnets
echo " "
curl -X POST -H "Content-Type: application/json" -d '{"subnet": {"network_id": "00000000-0000-0000-0000-000000000000", "segment_id": "blah", "cidr": "10.4.0.0/16", "tenant_id": "derp", "ip_version": "4"}}' http://localhost:9696/v2.0/subnets
echo " "
echo "Create Networks: Complete - http://localhost:9696"
echo "------------------------------------------"
echo " MAC Range: AA:BB:CC"
echo " NETWORK: 00000000-0000-0000-0000-000000000000"
echo " CIDR: 10.1.0.0/16 SEGMENT_ID: blah TENANT_ID: derp"
echo " CIDR: 10.2.0.0/16 SEGMENT_ID: blah TENANT_ID: derp"
echo " CIDR: 10.3.0.0/16 SEGMENT_ID: blah TENANT_ID: derp"
echo " CIDR: 10.4.0.0/16 SEGMENT_ID: blah TENANT_ID: derp"
echo "------------------------------------------"
echo " COMPLETE!!"
echo "------------------------------------------"