Start of the CORD configuration
diff --git a/cord-hosts b/cord-hosts
new file mode 100644
index 0000000..3a85337
--- /dev/null
+++ b/cord-hosts
@@ -0,0 +1,7 @@
+head ansible_ssh_host=node1.juju2.xos-pg0.clemson.cloudlab.us
+
+[compute]
+node2.juju2.xos-pg0.clemson.cloudlab.us
+
+[all:vars]
+cloudlab=true
diff --git a/cord-post-install.yml b/cord-post-install.yml
new file mode 100644
index 0000000..a46bfd9
--- /dev/null
+++ b/cord-post-install.yml
@@ -0,0 +1,23 @@
+# Play: Create credentials, set up some basic OpenStack
+- hosts: head
+ sudo: no
+ tasks:
+
+ - shell: uvt-kvm ip keystone
+ register: keystone_ip
+
+ - name: Create credentials
+ template: src=templates/admin-openrc-cord.sh.j2
+ dest={{ ansible_env['PWD'] }}/admin-openrc-cord.sh
+
+ - name: Copy credentials to nova-cloud-controller
+ shell: "scp admin-openrc.sh ubuntu@nova-cloud-controller:"
+
+ - name: Copy network setup script
+ sudo: yes
+ copy: src=scripts/network-setup.sh
+ dest=/usr/local/src/network-setup.sh
+ mode=0644
+
+ - name: Run network setup script
+ shell: ansible nova-cloud-controller -m script -u ubuntu -a "/usr/local/src/network-setup.sh"
diff --git a/cord-setup.yml b/cord-setup.yml
new file mode 100644
index 0000000..80e5a53
--- /dev/null
+++ b/cord-setup.yml
@@ -0,0 +1,213 @@
+---
+# Play: set up head node
+- hosts: head
+ sudo: yes
+ tasks:
+
+ - apt: name={{ item }} update_cache=yes
+ with_items:
+ - python-pycurl
+ - software-properties-common
+
+ - name: Add Juju repository
+ apt_repository: repo="ppa:juju/stable"
+
+ - name: Add Ansible repository
+ apt_repository: repo="ppa:ansible/ansible"
+
+ - name: Update Ansible cache
+ apt: update_cache=yes
+
+ - name: Install packages
+ apt: name={{ item }} state=latest
+ with_items:
+ - ansible
+ - uvtool
+ - git
+ - bzr
+ - juju-core
+ - juju-quickstart
+ - python-novaclient
+ - python-neutronclient
+ - python-keystoneclient
+ - python-glanceclient
+
+ - name: Get juju-ansible git repo
+ git: repo=https://github.com/cmars/juju-ansible.git
+ dest=/usr/local/src/juju-ansible
+
+ - name: Set up juju-ansible symlink
+ file: dest=/usr/local/bin/juju-ansible
+ src=/usr/local/src/juju-ansible/juju-ansible
+ state=link
+
+ - name: Set up juju-ansible-playbook symlink
+ file: dest=/usr/local/bin/juju-ansible-playbook
+ src=/usr/local/src/juju-ansible/juju-ansible
+ state=link
+
+ - name: Generate key to use in VMs
+ user: name={{ ansible_env['SUDO_USER'] }} generate_ssh_key=yes
+
+ - name: Get public key
+ shell: cat {{ ansible_env['PWD'] }}/.ssh/id_rsa.pub
+ register: sshkey
+
+ - name: Add key
+ authorized_key: user="{{ ansible_env['SUDO_USER'] }}"
+ key="{{ sshkey.stdout }}"
+
+ - name: (CloudLab) Set up extra disk space
+ shell: /usr/testbed/bin/mkextrafs -f /var/lib/uvtool/libvirt/images
+ creates=/var/lib/uvtool/libvirt/images/lost+found
+ when: cloudlab
+
+ - name: Add myself to libvirtd group
+ user: name={{ ansible_env['SUDO_USER'] }}
+ groups=libvirtd
+ append=yes
+
+ - name: Get trusty image for uvtool
+ shell: uvt-simplestreams-libvirt sync --source http://cloud-images.ubuntu.com/daily release=trusty arch=amd64
+
+# Play: create VMs to host OpenStack services
+- hosts: head
+ sudo: yes
+ tasks:
+ - name: Create VMs to host OpenCloud services
+ sudo: no
+ script: scripts/create-vms.sh
+
+ - include: tasks/vm-ips.yml
+
+ - name: Add VMs to /etc/hosts
+ template: src=templates/etc/hosts.j2
+ dest=/etc/hosts
+ notify:
+ - Reload dnsmasq
+
+ - name: Set up /etc/ansible/hosts
+ template: src=templates/etc/ansible/hosts.j2
+ dest=/etc/ansible/hosts
+
+ - name: Copy ansible.cfg to disable host key checking
+ sudo: no
+ copy: src=files/ansible.cfg
+ dest={{ ansible_env['PWD'] }}/.ansible.cfg
+
+ - name: Touch ~/.ssh/config
+ sudo: no
+ file: path={{ ansible_env['PWD'] }}/.ssh/config state=touch
+
+ - name: Disable host key checking in SSH
+ sudo: no
+ lineinfile: dest={{ ansible_env['PWD'] }}/.ssh/config
+ line="StrictHostKeyChecking no"
+
+ - name: Test that we can log into every VM
+ sudo: no
+ shell: ansible services -m ping -u ubuntu
+
+ handlers:
+ - name: Reload dnsmasq
+ shell: killall -HUP dnsmasq
+
+# Play: prepare compute nodes for installation
+- hosts: compute
+ sudo: yes
+ vars:
+ control_net: "{{ hostvars['head']['ansible_virbr0']['ipv4']['network'] }}/24"
+ gateway: "{{ hostvars['head']['ansible_default_ipv4']['address'] }}"
+ tasks:
+ - name: Install package needed by Juju
+ apt: name=python-yaml state=present
+
+ - name: Add key
+ authorized_key: user="{{ ansible_env['SUDO_USER'] }}"
+ key="{{ hostvars['head']['sshkey']['stdout'] }}"
+
+ - name: Add route via /etc/rc.local
+ template: src=templates/etc/rc.local.cloudlab
+ dest=/etc/rc.local
+ mode=0755
+ when: cloudlab
+ notify:
+ - run /etc/rc.local
+
+ - name: Add route via /etc/rc.local
+ template: src=templates/etc/rc.local
+ dest=/etc/rc.local
+ mode=0755
+ when: not cloudlab
+ notify:
+ - run /etc/rc.local
+
+ - name: Touch ~/.ssh/config
+ file: path=/var/lib/nova state=directory
+
+ - name: (CloudLab) Set up extra disk space
+ shell: /usr/testbed/bin/mkextrafs -f /var/lib/nova
+ creates=/var/lib/nova/lost+found
+ when: cloudlab
+
+ handlers:
+ - name: run /etc/rc.local
+ shell: /etc/rc.local
+
+# Play: Use libvirt hooks to set up iptables
+- hosts: head
+ sudo: yes
+ tasks:
+ - name: Enable port forwarding for services
+ copy: src=files/{{ item }}
+ dest={{ item }}
+ mode=0755
+ notify:
+ - reload libvirt config
+ - run qemu hook
+ with_items:
+# - /etc/libvirt/hooks/daemon
+ - /etc/libvirt/hooks/qemu
+
+ handlers:
+ - name: reload libvirt config
+ shell: killall -HUP libvirtd
+
+ - name: run qemu hook
+ shell: /etc/libvirt/hooks/qemu start start
+
+# Play: Install services using Juju
+- hosts: head
+ vars:
+ charm_src: /usr/local/src/charms/trusty
+ tasks:
+ - name: Initialize Juju
+ sudo: no
+ shell: juju generate-config
+ creates={{ ansible_env['PWD'] }}/.juju/environments.yaml
+
+ - shell: uvt-kvm ip juju
+ register: juju_ip
+
+ - name: Juju config file
+ sudo: no
+ template: src=templates/environments.yaml.j2
+ dest={{ ansible_env['PWD'] }}/.juju/environments.yaml
+
+ - name: Bootstrap Juju
+ sudo: no
+ shell: juju bootstrap
+ creates={{ ansible_env['PWD'] }}/.juju/environments/manual.jenv
+
+ - name: Add virtual machines to Juju's control
+ script: scripts/juju-cord-setup.py
+
+ - name: Add compute nodes to Juju's control
+ shell: juju add-machine ssh:{{ item }}
+ with_items: "{{ groups['compute'] }}"
+
+ - name: Copy cord.yaml bundle
+ copy: src=cord.yaml dest={{ ansible_env['PWD'] }}/cord.yaml
+
+ - name: Deploy OpenStack services with Juju
+ shell: juju quickstart cord.yaml
diff --git a/cord.yaml b/cord.yaml
new file mode 100644
index 0000000..4332a95
--- /dev/null
+++ b/cord.yaml
@@ -0,0 +1,251 @@
+machines:
+ '1':
+ constraints: arch=amd64
+ '2':
+ constraints: arch=amd64
+ '3':
+ constraints: arch=amd64
+ '4':
+ constraints: arch=amd64
+ '5':
+ constraints: arch=amd64
+ '6':
+ constraints: arch=amd64
+ '7':
+ constraints: arch=amd64
+ '8':
+ constraints: arch=amd64
+ '9':
+ constraints: arch=amd64
+ '10':
+ constraints: arch=amd64
+ '11':
+ constraints: arch=amd64
+relations:
+- - nova-compute:amqp
+ - rabbitmq-server:amqp
+- - neutron-gateway:amqp
+ - rabbitmq-server:amqp
+- - keystone:shared-db
+ - mysql:shared-db
+- - nova-cloud-controller:identity-service
+ - keystone:identity-service
+- - glance:identity-service
+ - keystone:identity-service
+- - neutron-api:identity-service
+ - keystone:identity-service
+- - neutron-openvswitch:neutron-plugin-api
+ - neutron-api:neutron-plugin-api
+- - neutron-api:shared-db
+ - mysql:shared-db
+- - neutron-api:amqp
+ - rabbitmq-server:amqp
+- - neutron-gateway:neutron-plugin-api
+ - neutron-api:neutron-plugin-api
+- - glance:shared-db
+ - mysql:shared-db
+- - glance:amqp
+ - rabbitmq-server:amqp
+- - nova-cloud-controller:image-service
+ - glance:image-service
+- - nova-compute:image-service
+ - glance:image-service
+- - nova-cloud-controller:cloud-compute
+ - nova-compute:cloud-compute
+- - nova-cloud-controller:amqp
+ - rabbitmq-server:amqp
+- - nova-cloud-controller:quantum-network-service
+ - neutron-gateway:quantum-network-service
+- - nova-compute:neutron-plugin
+ - neutron-openvswitch:neutron-plugin
+- - neutron-openvswitch:amqp
+ - rabbitmq-server:amqp
+- - openstack-dashboard:identity-service
+ - keystone:identity-service
+- - nova-cloud-controller:shared-db
+ - mysql:shared-db
+- - nova-cloud-controller:neutron-api
+ - neutron-api:neutron-api
+- - ntp:juju-info
+ - nova-compute:juju-info
+- - ntp:juju-info
+ - neutron-gateway:juju-info
+- - nagios
+ - nrpe
+- - mysql:juju-info
+ - nrpe:general-info
+- - rabbitmq-server
+ - nrpe
+- - keystone
+ - nrpe
+- - glance
+ - nrpe
+- - nova-cloud-controller
+ - nrpe
+- - neutron-gateway
+ - nrpe
+- - openstack-dashboard
+ - nrpe
+- - neutron-api
+ - nrpe
+- - ceilometer
+ - mongodb
+- - ceilometer
+ - rabbitmq-server
+- - ceilometer:identity-service
+ - keystone:identity-service
+- - ceilometer:ceilometer-service
+ - ceilometer-agent:ceilometer-service
+- - ceilometer
+ - nagios
+- - ceilometer
+ - nrpe
+- - nova-compute
+ - nagios
+- - nova-compute
+ - nrpe
+- - nova-compute:nova-ceilometer
+ - ceilometer-agent:nova-ceilometer
+series: trusty
+services:
+ ceilometer:
+ charm: cs:trusty/ceilometer-17
+ num_units: 1
+ options:
+ openstack-origin: cloud:trusty-kilo
+ to:
+ - '8'
+ ceilometer-agent:
+ charm: cs:trusty/ceilometer-agent-13
+ num_units: 0
+ glance:
+ annotations:
+ gui-x: '250'
+ gui-y: '0'
+ charm: cs:trusty/glance-28
+ num_units: 1
+ options:
+ ha-mcastport: 5402
+ openstack-origin: cloud:trusty-kilo
+ to:
+ - '4'
+ keystone:
+ annotations:
+ gui-x: '500'
+ gui-y: '0'
+ charm: cs:trusty/keystone-31
+ num_units: 1
+ options:
+ admin-password: 'ADMIN_PASS'
+ ha-mcastport: 5403
+ https-service-endpoints: False
+ openstack-origin: cloud:trusty-kilo
+ use-https: no
+ to:
+ - '3'
+ mongodb:
+ charm: cs:trusty/mongodb-33
+ num_units: 1
+ to:
+ - '8'
+ mysql:
+ annotations:
+ gui-x: '0'
+ gui-y: '250'
+ charm: cs:trusty/percona-cluster-31
+ num_units: 1
+ options:
+ max-connections: 20000
+ to:
+ - '1'
+ nagios:
+ charm: cs:trusty/nagios-10
+ num_units: 1
+ to:
+ - '9'
+ neutron-api:
+ annotations:
+ gui-x: '500'
+ gui-y: '500'
+ charm: cs:trusty/neutron-api-21
+ num_units: 1
+ options:
+ #neutron-security-groups: true
+ openstack-origin: cloud:trusty-kilo
+ to:
+ - '10'
+ neutron-gateway:
+ annotations:
+ gui-x: '0'
+ gui-y: '0'
+ charm: cs:trusty/neutron-gateway-7
+ num_units: 1
+ options:
+ #ext-port: eth1
+ openstack-origin: cloud:trusty-kilo
+ to:
+ - '6'
+ neutron-openvswitch:
+ annotations:
+ gui-x: '250'
+ gui-y: '500'
+ charm: cs:trusty/neutron-openvswitch-13
+ num_units: 0
+ nova-cloud-controller:
+ annotations:
+ gui-x: '0'
+ gui-y: '500'
+ charm: cs:trusty/nova-cloud-controller-64
+ num_units: 1
+ options:
+ console-access-protocol: novnc
+ network-manager: Neutron
+ openstack-origin: cloud:trusty-kilo
+ #quantum-security-groups: 'yes'
+ to:
+ - '5'
+ nova-compute:
+ annotations:
+ gui-x: '250'
+ gui-y: '250'
+ charm: cs:trusty/nova-compute-33
+ num_units: 1
+ options:
+ config-flags: firewall_driver=nova.virt.firewall.NoopFirewallDriver
+ disable-neutron-security-groups: True
+ #enable-live-migration: true
+ #enable-resize: true
+ #migration-auth-type: ssh
+ openstack-origin: cloud:trusty-kilo
+ #manage-neutron-plugin-legacy-mode: False
+ to:
+ - '11'
+ nrpe:
+ charm: cs:trusty/nrpe-4
+ num_units: 0
+ ntp:
+ annotations:
+ gui-x: '1000'
+ gui-y: '0'
+ charm: cs:trusty/ntp-14
+ num_units: 0
+ openstack-dashboard:
+ annotations:
+ gui-x: '500'
+ gui-y: '-250'
+ charm: cs:trusty/openstack-dashboard-19
+ num_units: 1
+ options:
+ openstack-origin: cloud:trusty-kilo
+ to:
+ - '7'
+ rabbitmq-server:
+ annotations:
+ gui-x: '500'
+ gui-y: '250'
+ charm: cs:trusty/rabbitmq-server-42
+ num_units: 1
+ options:
+ ssl: 'off'
+ to:
+ - '2'
diff --git a/scripts/juju-cord-setup.py b/scripts/juju-cord-setup.py
new file mode 100755
index 0000000..ba19ffd
--- /dev/null
+++ b/scripts/juju-cord-setup.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+import subprocess
+import json
+import socket
+
+# Assumption: VMs have same hostname as service that runs inside
+machines = ["mysql", "rabbitmq-server", "keystone", "glance", "nova-cloud-controller",
+ "neutron-gateway", "openstack-dashboard", "ceilometer", "nagios", "neutron-api"]
+
+
+# Figure out Juju ID of machine we should install on
+def get_machine(status, service):
+ if service == "mongodb":
+ service = "ceilometer"
+ for key, value in status['machines'].iteritems():
+ (hostname, aliaslist, ipaddrlist) = socket.gethostbyaddr(value['dns-name'])
+ if hostname == service:
+ return key
+ return None
+
+def get_juju_status():
+ output = subprocess.check_output("juju status --format=json", shell=True)
+ status = json.loads(output)
+ return status
+
+def addmachines():
+ status = get_juju_status()
+
+ for machine in machines:
+ if get_machine(status, machine) == None:
+ ipaddr = socket.gethostbyname(machine)
+ subprocess.check_call("juju add-machine ssh:%s" % ipaddr, shell=True)
+
+def main():
+ addmachines()
+
+if __name__ =='__main__':
+ main()
diff --git a/templates/admin-openrc-cord.sh.j2 b/templates/admin-openrc-cord.sh.j2
new file mode 100644
index 0000000..ec7ab9d
--- /dev/null
+++ b/templates/admin-openrc-cord.sh.j2
@@ -0,0 +1,5 @@
+export OS_USERNAME=admin
+export OS_PASSWORD=ADMIN_PASS
+export OS_TENANT_NAME=admin
+export OS_AUTH_URL=http://{{ keystone_ip.stdout }}:5000/v2.0
+export OS_REGION_NAME=RegionOne