commit
95df650ae2
2
.gitignore
vendored
2
.gitignore
vendored
@ -33,3 +33,5 @@ bootstrap/solar-master.box
|
|||||||
vagrant-settings.yml
|
vagrant-settings.yml
|
||||||
|
|
||||||
.solar_cli_uids
|
.solar_cli_uids
|
||||||
|
|
||||||
|
.ssh/
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
apt: name={{ item }} state=present
|
apt: name={{ item }} state=present
|
||||||
with_items:
|
with_items:
|
||||||
- git
|
- git
|
||||||
|
- subversion
|
||||||
- python-mock
|
- python-mock
|
||||||
- python-keystoneclient
|
- python-keystoneclient
|
||||||
- python-mysqldb
|
- python-mysqldb
|
||||||
|
146
example-lxc.py
Normal file
146
example-lxc.py
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# To run:
|
||||||
|
# example-lxc.py deploy
|
||||||
|
# solar changes stage
|
||||||
|
# solar changes process
|
||||||
|
# solar orch run-once last
|
||||||
|
# watch 'solar orch report last'
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from solar.core import signals
|
||||||
|
from solar.core.resource import virtual_resource as vr
|
||||||
|
|
||||||
|
from solar.interfaces.db import get_db
|
||||||
|
|
||||||
|
from solar.system_log import change
|
||||||
|
from solar.cli import orch
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def main():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def lxc_template(idx):
|
||||||
|
return {
|
||||||
|
'user': 'root',
|
||||||
|
'mgmt_ip': '172.18.11.{}'.format(idx),
|
||||||
|
'container_name': 'test{}'.format(idx),
|
||||||
|
'inventory_hostname': 'test{}'.format(idx),
|
||||||
|
'properties':
|
||||||
|
{'container_release': 'trusty'},
|
||||||
|
'container_networks':
|
||||||
|
{'mgmt': {
|
||||||
|
'address': '172.18.11.{}'.format(idx), # address for container
|
||||||
|
'bridge': 'br-int53', # bridge to attach veth pair
|
||||||
|
'bridge_address': '172.18.11.253/24',
|
||||||
|
'interface': 'eth1', # interface name in container
|
||||||
|
'netmask': '255.255.255.0',
|
||||||
|
'type': 'veth'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
def deploy():
|
||||||
|
db = get_db()
|
||||||
|
db.clear()
|
||||||
|
signals.Connections.clear()
|
||||||
|
|
||||||
|
node1 = vr.create('nodes', 'templates/nodes.yml', {})[0]
|
||||||
|
seed = vr.create('nodes', 'templates/seed_node.yml', {})[0]
|
||||||
|
|
||||||
|
ssh_key = vr.create('ssh_key1', 'resources/ssh_key', {
|
||||||
|
'keys_dir': '/vagrant/.ssh',
|
||||||
|
'private_key': '/vagrant/.ssh/id_rsa',
|
||||||
|
'public_key': '/vagrant/.ssh/id_rsa.pub',
|
||||||
|
'passphrase': '',
|
||||||
|
})[0]
|
||||||
|
signals.connect(seed, ssh_key)
|
||||||
|
|
||||||
|
cnets1 = vr.create('cnets1', 'resources/container_networks', {
|
||||||
|
'networks':
|
||||||
|
{'mgmt': {
|
||||||
|
'bridge': 'br-int53',
|
||||||
|
'bridge_address': '172.18.11.254/24'
|
||||||
|
}}
|
||||||
|
})[0]
|
||||||
|
cnets2 = vr.create('cnets2', 'resources/container_networks', {
|
||||||
|
'networks':
|
||||||
|
{'mgmt': {
|
||||||
|
'bridge': 'br-int53',
|
||||||
|
'bridge_address': '172.18.11.253/24'
|
||||||
|
}}
|
||||||
|
})[0]
|
||||||
|
signals.connect(seed, cnets1)
|
||||||
|
signals.connect(node1, cnets2)
|
||||||
|
|
||||||
|
vxlan_mesh1 = vr.create('vxlan_mesh1', 'resources/vxlan_mesh', {
|
||||||
|
'id': 53,
|
||||||
|
'parent': 'eth1',
|
||||||
|
'master': 'br-int53'
|
||||||
|
})[0]
|
||||||
|
vxlan_mesh2 = vr.create('vxlan_mesh2', 'resources/vxlan_mesh', {
|
||||||
|
'id': 53,
|
||||||
|
'parent': 'eth1',
|
||||||
|
'master': 'br-int53'
|
||||||
|
})[0]
|
||||||
|
# seed node should be connected anyway, because we need to be able to ssh
|
||||||
|
# into containers from any node
|
||||||
|
signals.connect(seed, vxlan_mesh1)
|
||||||
|
signals.connect(node1, vxlan_mesh2)
|
||||||
|
|
||||||
|
lxc_infra1 = vr.create('lxc_infra1', 'resources/lxc_host', {})[0]
|
||||||
|
signals.connect(node1, lxc_infra1)
|
||||||
|
|
||||||
|
lxc_hosts = range(28, 35)
|
||||||
|
hosts_map = {}
|
||||||
|
for idx in lxc_hosts:
|
||||||
|
|
||||||
|
lxc_host_idx = vr.create(
|
||||||
|
'lxc_host{}'.format(idx),
|
||||||
|
'resources/lxc_container', lxc_template(idx))[0]
|
||||||
|
hosts_map[idx] = lxc_host_idx
|
||||||
|
|
||||||
|
signals.connect(node1, lxc_host_idx, {
|
||||||
|
'ip': ['ansible_ssh_host', 'physical_host'],
|
||||||
|
})
|
||||||
|
# this is a required to introduce depends on relationship between lxc infre
|
||||||
|
# and lxc container
|
||||||
|
signals.connect(lxc_infra1, lxc_host_idx, {'provides': 'requires'})
|
||||||
|
signals.connect(cnets2, lxc_host_idx)
|
||||||
|
signals.connect(ssh_key, lxc_host_idx, {
|
||||||
|
'public_key': 'pub_key',
|
||||||
|
'private_key': 'user_key'})
|
||||||
|
|
||||||
|
# RABBIT
|
||||||
|
rabbitmq_service1 = vr.create('rabbitmq_service1', 'resources/rabbitmq_service/', {
|
||||||
|
'management_port': 15672,
|
||||||
|
'port': 5672,
|
||||||
|
})[0]
|
||||||
|
openstack_vhost = vr.create('openstack_vhost', 'resources/rabbitmq_vhost/', {
|
||||||
|
'vhost_name': 'openstack'
|
||||||
|
})[0]
|
||||||
|
|
||||||
|
openstack_rabbitmq_user = vr.create('openstack_rabbitmq_user', 'resources/rabbitmq_user/', {
|
||||||
|
'user_name': 'openstack',
|
||||||
|
'password': 'openstack_password'
|
||||||
|
})[0]
|
||||||
|
|
||||||
|
signals.connect(hosts_map[28], rabbitmq_service1, {
|
||||||
|
'mgmt_ip': 'ip',
|
||||||
|
'user_key': 'ssh_key',
|
||||||
|
'user': 'ssh_user'})
|
||||||
|
signals.connect(rabbitmq_service1, openstack_vhost)
|
||||||
|
signals.connect(rabbitmq_service1, openstack_rabbitmq_user)
|
||||||
|
signals.connect(openstack_vhost, openstack_rabbitmq_user, {
|
||||||
|
'vhost_name',
|
||||||
|
})
|
||||||
|
|
||||||
|
print change.send_to_orchestration()
|
||||||
|
|
||||||
|
main.add_command(deploy)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
22
resources/container_networks/actions/run.yml
Normal file
22
resources/container_networks/actions/run.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
- hosts: '*'
|
||||||
|
sudo: yes
|
||||||
|
gather_facts: false
|
||||||
|
# this is default variables, they will be overwritten by resource one
|
||||||
|
vars:
|
||||||
|
networks:
|
||||||
|
mgmt:
|
||||||
|
address: 172.18.10.6
|
||||||
|
bridge: br-test0
|
||||||
|
bridge_address: 172.18.10.252/24
|
||||||
|
interface: eth1
|
||||||
|
netmask: 255.255.255.0
|
||||||
|
type: veth
|
||||||
|
tasks:
|
||||||
|
- shell: ip l add {{item.value.bridge}} type bridge
|
||||||
|
with_dict: networks
|
||||||
|
ignore_errors: true
|
||||||
|
- shell: ip l set {{item.value.bridge}} up
|
||||||
|
with_dict: networks
|
||||||
|
- shell: ip a add dev {{item.value.bridge}} {{item.value.bridge_address}}
|
||||||
|
with_dict: networks
|
||||||
|
ignore_errors: true
|
17
resources/container_networks/meta.yaml
Normal file
17
resources/container_networks/meta.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
id: container_networks
|
||||||
|
handler: ansible_playbook
|
||||||
|
version: 1.0.0
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
networks:
|
||||||
|
schema: {}
|
||||||
|
value:
|
25
resources/lxc_container/actions/run.yml
Normal file
25
resources/lxc_container/actions/run.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
- hosts: '*'
|
||||||
|
sudo: yes
|
||||||
|
gather_facts: false
|
||||||
|
# this is default variables, they will be overwritten by resource one
|
||||||
|
vars:
|
||||||
|
ansible_ssh_host: 10.0.0.3
|
||||||
|
physical_host: 10.0.0.3
|
||||||
|
container_name: test3
|
||||||
|
inventory_hostname: test3
|
||||||
|
properties:
|
||||||
|
container_release: trusty
|
||||||
|
container_networks:
|
||||||
|
mgmt:
|
||||||
|
address: 172.18.10.6
|
||||||
|
bridge: br-test0
|
||||||
|
bridge_address: 172.18.10.252/24
|
||||||
|
interface: eth1
|
||||||
|
netmask: 255.255.255.0
|
||||||
|
type: veth
|
||||||
|
pub_key: ''
|
||||||
|
pre_tasks:
|
||||||
|
- set_fact:
|
||||||
|
lxc_container_ssh_key: "{{ lookup('file', pub_key) }}"
|
||||||
|
roles:
|
||||||
|
- { role: "lxc_container_create", tags: [ "lxc-container-create" ] }
|
55
resources/lxc_container/meta.yaml
Normal file
55
resources/lxc_container/meta.yaml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
id: lxc_container
|
||||||
|
handler: ansible_playbook
|
||||||
|
version: 1.0.0
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ansible_ssh_host:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
user_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
mgmt_ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
physical_host:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
container_address:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
container_name:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
inventory_hostname:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
container_networks:
|
||||||
|
schema: {}
|
||||||
|
value:
|
||||||
|
properties:
|
||||||
|
schema: {}
|
||||||
|
value:
|
||||||
|
pub_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
requires:
|
||||||
|
schema: str
|
||||||
|
value:
|
||||||
|
roles:
|
||||||
|
schema: [{value: str}]
|
||||||
|
value:
|
||||||
|
- https://github.com/stackforge/os-ansible-deployment/trunk/playbooks/roles/lxc_container_create
|
||||||
|
- https://github.com/stackforge/os-ansible-deployment/trunk/playbooks/roles/lxc_container_destroy
|
6
resources/lxc_host/actions/run.yml
Normal file
6
resources/lxc_host/actions/run.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- hosts: '*'
|
||||||
|
sudo: yes
|
||||||
|
roles:
|
||||||
|
- { role: "lxc_hosts", tags: [ "lxc-host", "host-setup" ] }
|
||||||
|
post_tasks:
|
||||||
|
- shell: pip install git+https://github.com/lxc/python2-lxc.git#egg=lxc
|
23
resources/lxc_host/meta.yaml
Normal file
23
resources/lxc_host/meta.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
id: lxc_host
|
||||||
|
handler: ansible_playbook
|
||||||
|
version: 1.0.0
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
provides:
|
||||||
|
schema: str
|
||||||
|
value: infra
|
||||||
|
roles:
|
||||||
|
schema: [{value: str}]
|
||||||
|
value:
|
||||||
|
- https://github.com/stackforge/os-ansible-deployment/trunk/playbooks/roles/lxc_hosts
|
||||||
|
- https://github.com/stackforge/os-ansible-deployment/trunk/playbooks/roles/pip_install
|
||||||
|
- https://github.com/stackforge/os-ansible-deployment/trunk/playbooks/roles/apt_package_pinning
|
14
resources/ssh_key/actions/run.yml
Normal file
14
resources/ssh_key/actions/run.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
- hosts: '*'
|
||||||
|
sudo: yes
|
||||||
|
gather_facts: false
|
||||||
|
# this is default variables, they will be overwritten by resource one
|
||||||
|
vars:
|
||||||
|
keys_dir: /vagrant/.ssh
|
||||||
|
private_key: /vagrant/.ssh/id_rsa
|
||||||
|
passphrase: ''
|
||||||
|
tasks:
|
||||||
|
- shell: mkdir -p {{keys_dir}}
|
||||||
|
- stat: path={{private_key}}
|
||||||
|
register: key
|
||||||
|
- shell: ssh-keygen -t rsa -f {{private_key}} -N ""
|
||||||
|
when: key.stat.exists == False
|
26
resources/ssh_key/meta.yaml
Normal file
26
resources/ssh_key/meta.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
id: ssh_key
|
||||||
|
handler: ansible_playbook
|
||||||
|
version: 1.0.0
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
keys_dir:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
private_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
public_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
passphrase:
|
||||||
|
schema: str
|
||||||
|
value:
|
16
resources/vxlan_mesh/actions/run.yml
Normal file
16
resources/vxlan_mesh/actions/run.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
- hosts: '*'
|
||||||
|
sudo: yes
|
||||||
|
vars:
|
||||||
|
id: 42
|
||||||
|
group: 239.1.10.2
|
||||||
|
parent: eth1
|
||||||
|
master: br-test0
|
||||||
|
tasks:
|
||||||
|
- name: add vxlan mesh
|
||||||
|
shell: ip l add vxlan{{id}} type vxlan id {{id}}
|
||||||
|
group {{group}} dev {{parent}}
|
||||||
|
ignore_errors: true
|
||||||
|
- name: set vxlan master
|
||||||
|
shell: ip l set vxlan{{id}} master {{master}}
|
||||||
|
- name: set vxlan tunnel up
|
||||||
|
shell: ip l set vxlan{{id}} up
|
23
resources/vxlan_mesh/meta.yaml
Normal file
23
resources/vxlan_mesh/meta.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
id: vxlan_mesh
|
||||||
|
handler: ansible_playbook
|
||||||
|
version: 1.0.0
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
ip:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_key:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
ssh_user:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
parent:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
master:
|
||||||
|
schema: str!
|
||||||
|
value:
|
||||||
|
id:
|
||||||
|
schema: int!
|
||||||
|
value:
|
@ -16,3 +16,4 @@ Fabric==1.10.2
|
|||||||
tabulate==0.7.5
|
tabulate==0.7.5
|
||||||
ansible
|
ansible
|
||||||
celery
|
celery
|
||||||
|
mock
|
||||||
|
@ -6,13 +6,27 @@ from ansible.playbook import PlayBook
|
|||||||
from ansible import utils
|
from ansible import utils
|
||||||
from ansible import callbacks
|
from ansible import callbacks
|
||||||
import ansible.constants as C
|
import ansible.constants as C
|
||||||
|
from fabric import api as fabric_api
|
||||||
|
|
||||||
from solar.core.handlers import base
|
from solar.core.handlers import base
|
||||||
from solar import errors
|
from solar import errors
|
||||||
|
from solar.core.provider import SVNProvider
|
||||||
|
|
||||||
|
|
||||||
|
ROLES_PATH = '/etc/ansible/roles'
|
||||||
|
|
||||||
|
|
||||||
class AnsiblePlaybook(base.BaseHandler):
|
class AnsiblePlaybook(base.BaseHandler):
|
||||||
|
|
||||||
|
def download_roles(self, urls):
|
||||||
|
if not os.path.exists(ROLES_PATH):
|
||||||
|
os.makedirs(ROLES_PATH)
|
||||||
|
for url in urls:
|
||||||
|
provider = SVNProvider(url)
|
||||||
|
provider.run()
|
||||||
|
fabric_api.local('cp -r {} {}'.format(
|
||||||
|
provider.directory, ROLES_PATH))
|
||||||
|
|
||||||
def action(self, resource, action):
|
def action(self, resource, action):
|
||||||
action_file = os.path.join(
|
action_file = os.path.join(
|
||||||
resource.metadata['actions_path'],
|
resource.metadata['actions_path'],
|
||||||
@ -22,6 +36,9 @@ class AnsiblePlaybook(base.BaseHandler):
|
|||||||
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
|
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
|
||||||
|
|
||||||
variables = resource.args_dict()
|
variables = resource.args_dict()
|
||||||
|
if 'roles' in variables:
|
||||||
|
self.download_roles(variables['roles'])
|
||||||
|
|
||||||
remote_user = variables.get('ssh_user') or C.DEFAULT_REMOTE_USER
|
remote_user = variables.get('ssh_user') or C.DEFAULT_REMOTE_USER
|
||||||
private_key_file = variables.get('ssh_key') or C.DEFAULT_PRIVATE_KEY_FILE
|
private_key_file = variables.get('ssh_key') or C.DEFAULT_PRIVATE_KEY_FILE
|
||||||
if variables.get('ip'):
|
if variables.get('ip'):
|
||||||
@ -30,7 +47,7 @@ class AnsiblePlaybook(base.BaseHandler):
|
|||||||
else:
|
else:
|
||||||
host = 'localhost'
|
host = 'localhost'
|
||||||
transport = 'local'
|
transport = 'local'
|
||||||
|
C.HOST_KEY_CHECKING = False
|
||||||
play = PlayBook(
|
play = PlayBook(
|
||||||
playbook=action_file,
|
playbook=action_file,
|
||||||
remote_user=remote_user,
|
remote_user=remote_user,
|
||||||
|
@ -103,3 +103,29 @@ class RemoteZipProvider(BaseProvider):
|
|||||||
self.directory = os.path.join(directory, path)
|
self.directory = os.path.join(directory, path)
|
||||||
else:
|
else:
|
||||||
self.directory = directory
|
self.directory = directory
|
||||||
|
|
||||||
|
|
||||||
|
class SVNProvider(BaseProvider):
|
||||||
|
"""With git you cant checkout only directory from repo,
|
||||||
|
but with svn you can
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url, path='.', base_path=None):
|
||||||
|
self.url = url
|
||||||
|
self.path = path
|
||||||
|
self.base_path = base_path or utils.read_config()['resources-directory']
|
||||||
|
if path != '.':
|
||||||
|
self.repo_directory = os.path.join(self.base_path, path)
|
||||||
|
else:
|
||||||
|
self.repo_directory = self.base_path
|
||||||
|
self.directory = os.path.join(self.repo_directory, self.url.rsplit('/', 1)[-1])
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not os.path.exists(self.repo_directory):
|
||||||
|
os.makedirs(self.repo_directory)
|
||||||
|
|
||||||
|
if not os.path.exists(self.directory):
|
||||||
|
fabric_api.local(
|
||||||
|
'cd {dir} && svn checkout {url}'.format(
|
||||||
|
dir=self.repo_directory,
|
||||||
|
url=self.url))
|
||||||
|
8
templates/seed_node.yml
Normal file
8
templates/seed_node.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
id: seed_node
|
||||||
|
resources:
|
||||||
|
- id: seed_node
|
||||||
|
from: resources/ro_node
|
||||||
|
values:
|
||||||
|
ip: '10.0.0.2'
|
||||||
|
ssh_key: '/vagrant/.vagrant/machines/solar-dev/virtualbox/private_key'
|
||||||
|
ssh_user: 'vagrant'
|
Loading…
Reference in New Issue
Block a user