Cyborg deployment script
This deploys cyborg services across various hosts and sets them up as boot time services configured to access the local rabbit and mysql instances and then runs some validations to ensure that everything started correctly. This does not have any saftey for multi-controller setups yet, right now if you hand the playbook 3 hosts under 'controller' it will deploy three api endpoints and three agents. Which probably won't work right. Change-Id: I79b6b1ce9bb6766d5e608c89504c4bbaeaba5599
This commit is contained in:
parent
4f5c85e654
commit
85ac496ff6
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.tox
|
*.tox
|
||||||
|
*.retry
|
||||||
*.testrepository
|
*.testrepository
|
||||||
cyborg.egg-info
|
cyborg.egg-info
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import pbr.version
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = pbr.version.VersionInfo(
|
|
||||||
'cyborg-agent').version_string()
|
|
@ -1,3 +0,0 @@
|
|||||||
[cyborg]
|
|
||||||
transport_url=
|
|
||||||
server_id=
|
|
@ -1,64 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
import conf
|
|
||||||
import eventlet
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log as logging
|
|
||||||
import oslo_messaging as messaging
|
|
||||||
import rpcapi
|
|
||||||
import time
|
|
||||||
|
|
||||||
eventlet.monkey_patch()
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
|
|
||||||
conf.register_opts(CONF)
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
logging.register_options(CONF)
|
|
||||||
logging.setup(CONF, 'Cyborg.Agent')
|
|
||||||
|
|
||||||
CONF(['--config-file', 'agent.conf'])
|
|
||||||
|
|
||||||
url = messaging.TransportURL.parse(CONF, url=CONF.cyborg.transport_url)
|
|
||||||
transport = messaging.get_notification_transport(CONF, url)
|
|
||||||
|
|
||||||
notifier = messaging.Notifier(transport,
|
|
||||||
driver='messaging',
|
|
||||||
publisher_id='Cyborg.Agent',
|
|
||||||
topic='info')
|
|
||||||
|
|
||||||
rpc_targets = messaging.Target(topic='cyborg_control',
|
|
||||||
server=CONF.cyborg.server_id)
|
|
||||||
rpc_endpoints = [
|
|
||||||
rpcapi.RPCEndpoint()
|
|
||||||
]
|
|
||||||
access_policy = messaging.ExplicitRPCAccessPolicy
|
|
||||||
rpc_server = messaging.get_rpc_server(transport,
|
|
||||||
rpc_targets,
|
|
||||||
rpc_endpoints,
|
|
||||||
executor='eventlet',
|
|
||||||
access_policy=access_policy)
|
|
||||||
|
|
||||||
try:
|
|
||||||
print("Cyborg Agent running")
|
|
||||||
rpc_server.start()
|
|
||||||
while True:
|
|
||||||
time.sleep(1)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print("Stopping server")
|
|
||||||
rpc_server.stop()
|
|
||||||
rpc_server.wait()
|
|
37
cyborg/agent/manager.py
Normal file
37
cyborg/agent/manager.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import oslo_messaging as messaging
|
||||||
|
|
||||||
|
from cyborg.conf import CONF
|
||||||
|
|
||||||
|
|
||||||
|
class AgentManager(object):
|
||||||
|
"""Cyborg Agent manager main class."""
|
||||||
|
|
||||||
|
RPC_API_VERSION = '1.0'
|
||||||
|
target = messaging.Target(version=RPC_API_VERSION)
|
||||||
|
|
||||||
|
def __init__(self, topic, host=None):
|
||||||
|
super(AgentManager, self).__init__()
|
||||||
|
self.topic = topic
|
||||||
|
self.host = host or CONF.host
|
||||||
|
|
||||||
|
def periodic_tasks(self, context, raise_on_error=False):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hardware_list(self, context, values):
|
||||||
|
"""List installed hardware."""
|
||||||
|
pass
|
@ -13,18 +13,40 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
"""Client side of the conductor RPC API."""
|
||||||
|
|
||||||
class RPCEndpoint(object):
|
from oslo_config import cfg
|
||||||
|
import oslo_messaging as messaging
|
||||||
|
|
||||||
# Conductor functions exposed for external calls
|
from cyborg.common import constants
|
||||||
def __init__(self):
|
from cyborg.common import rpc
|
||||||
pass
|
from cyborg.objects import base as objects_base
|
||||||
|
|
||||||
def list_accelerators(self, ctxt):
|
|
||||||
pass
|
CONF = cfg.CONF
|
||||||
|
|
||||||
def update_accelerator(self, ctxt, accelerator):
|
|
||||||
pass
|
class AgentAPI(object):
|
||||||
|
"""Client side of the Agent RPC API.
|
||||||
def discover_accelerators(self, ctxt):
|
|
||||||
|
API version history:
|
||||||
|
|
||||||
|
| 1.0 - Initial version.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
RPC_API_VERSION = '1.0'
|
||||||
|
|
||||||
|
def __init__(self, topic=None):
|
||||||
|
super(AgentAPI, self).__init__()
|
||||||
|
self.topic = topic or constants.AGENT_TOPIC
|
||||||
|
target = messaging.Target(topic=self.topic,
|
||||||
|
version='1.0')
|
||||||
|
serializer = objects_base.CyborgObjectSerializer()
|
||||||
|
self.client = rpc.get_client(target,
|
||||||
|
version_cap=self.RPC_API_VERSION,
|
||||||
|
serializer=serializer)
|
||||||
|
|
||||||
|
def hardware_list(self, context, values):
|
||||||
|
"""Signal the agent to find local hardware."""
|
||||||
pass
|
pass
|
||||||
|
@ -11,18 +11,27 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
"""The Cyborg Agent Service."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import uuid
|
from oslo_service import service
|
||||||
|
|
||||||
default_opts = [
|
from cyborg.common import constants
|
||||||
cfg.StrOpt('transport_url',
|
from cyborg.common import service as cyborg_service
|
||||||
default='',
|
|
||||||
help='Transport url to use for messaging'),
|
|
||||||
cfg.StrOpt('server_id',
|
|
||||||
default=uuid.uuid4(),
|
|
||||||
help='Unique identifier for this agent'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
CONF = cfg.CONF
|
||||||
conf.register_opts(default_opts, group='cyborg')
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Parse config file and command line options, then start logging
|
||||||
|
cyborg_service.prepare_service(sys.argv)
|
||||||
|
|
||||||
|
mgr = cyborg_service.RPCService('cyborg.agent.manager',
|
||||||
|
'AgentManager',
|
||||||
|
constants.AGENT_TOPIC)
|
||||||
|
|
||||||
|
launcher = service.launch(CONF, mgr)
|
||||||
|
launcher.wait()
|
@ -15,3 +15,4 @@
|
|||||||
|
|
||||||
|
|
||||||
CONDUCTOR_TOPIC = 'cyborg-conductor'
|
CONDUCTOR_TOPIC = 'cyborg-conductor'
|
||||||
|
AGENT_TOPIC = 'cyborg-agent'
|
||||||
|
@ -28,6 +28,7 @@ console_scripts =
|
|||||||
cyborg-api = cyborg.cmd.api:main
|
cyborg-api = cyborg.cmd.api:main
|
||||||
cyborg-conductor = cyborg.cmd.conductor:main
|
cyborg-conductor = cyborg.cmd.conductor:main
|
||||||
cyborg-dbsync = cyborg.cmd.dbsync:main
|
cyborg-dbsync = cyborg.cmd.dbsync:main
|
||||||
|
cyborg-agent = cyborg.cmd.agent:main
|
||||||
|
|
||||||
cyborg.database.migration_backend =
|
cyborg.database.migration_backend =
|
||||||
sqlalchemy = cyborg.db.sqlalchemy.migration
|
sqlalchemy = cyborg.db.sqlalchemy.migration
|
||||||
|
22
setup/deploy-cyborg.yml
Normal file
22
setup/deploy-cyborg.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# This Ansible playbook deploys Cyborg services on an openstack cloud
|
||||||
|
|
||||||
|
- hosts: controller
|
||||||
|
remote_user: heat-admin
|
||||||
|
roles:
|
||||||
|
- generate_credentials
|
||||||
|
- install_package
|
||||||
|
- template_config
|
||||||
|
- deploy_api
|
||||||
|
- deploy_conductor
|
||||||
|
- validate_api
|
||||||
|
- validate_conductor
|
||||||
|
|
||||||
|
- hosts: compute
|
||||||
|
remote_user: heat-admin
|
||||||
|
roles:
|
||||||
|
- install_package
|
||||||
|
- template_config
|
||||||
|
- deploy_agent
|
||||||
|
- validate_agent
|
||||||
|
#- deploy_drivers
|
22
setup/roles/deploy_agent/tasks/main.yml
Normal file
22
setup/roles/deploy_agent/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Sets up Cyborg api to start at boot
|
||||||
|
|
||||||
|
- name: Create Cyborg user
|
||||||
|
user:
|
||||||
|
name: cyborg
|
||||||
|
comment: "cyborg user"
|
||||||
|
createhome: no
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Template service file for Cyborg Agent
|
||||||
|
template:
|
||||||
|
src: openstack-cyborg-agent.service.j2
|
||||||
|
dest: /usr/lib/systemd/system/openstack-cyborg-agent.service
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Start service and set to run at boot
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-agent
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenStack Accelerator management service
|
||||||
|
After=syslog.target network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=cyborg
|
||||||
|
ExecStart=/usr/bin/cyborg-agent
|
||||||
|
PrivateTmp=true
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
22
setup/roles/deploy_api/tasks/main.yml
Normal file
22
setup/roles/deploy_api/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Sets up Cyborg api to start at boot
|
||||||
|
|
||||||
|
- name: Create Cyborg user
|
||||||
|
user:
|
||||||
|
name: cyborg
|
||||||
|
comment: "cyborg user"
|
||||||
|
createhome: no
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Template service file for Cyborg API
|
||||||
|
template:
|
||||||
|
src: openstack-cyborg-api.service.j2
|
||||||
|
dest: /usr/lib/systemd/system/openstack-cyborg-api.service
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Start service and set to run at boot
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-api
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenStack Accelerator management service
|
||||||
|
After=syslog.target network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=cyborg
|
||||||
|
ExecStart=/usr/bin/cyborg-api
|
||||||
|
PrivateTmp=true
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
22
setup/roles/deploy_conductor/tasks/main.yml
Normal file
22
setup/roles/deploy_conductor/tasks/main.yml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Sets up Cyborg api to start at boot
|
||||||
|
|
||||||
|
- name: Create Cyborg user
|
||||||
|
user:
|
||||||
|
name: cyborg
|
||||||
|
comment: "cyborg user"
|
||||||
|
createhome: no
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Template service file for Cyborg Conductor
|
||||||
|
template:
|
||||||
|
src: openstack-cyborg-conductor.service.j2
|
||||||
|
dest: /usr/lib/systemd/system/openstack-cyborg-conductor.service
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Start service and set to run at boot
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-conductor
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenStack Accelerator management service
|
||||||
|
After=syslog.target network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=glance
|
||||||
|
ExecStart=/usr/bin/cyborg-conductor
|
||||||
|
PrivateTmp=true
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
20
setup/roles/generate_credentials/tasks/main.yml
Normal file
20
setup/roles/generate_credentials/tasks/main.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Create Cyborg mysql user
|
||||||
|
mysql_user:
|
||||||
|
name: cyborg
|
||||||
|
password: "{{ lookup('password', 'credentials/cyborg/mysqlpassword length=15') }}" # Generates a password
|
||||||
|
priv: '*.*:ALL,GRANT' # Do we only need the cyborg database?
|
||||||
|
state: present
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Create Cyborg rabbitmq user
|
||||||
|
rabbitmq_user:
|
||||||
|
user: cyborg
|
||||||
|
password: "{{ lookup('password', 'credentials/cyborg/rabbitpassword length=15') }}" # Generates a password
|
||||||
|
vhost: /
|
||||||
|
read_priv: .*
|
||||||
|
write_priv: .*
|
||||||
|
configure_priv: .*
|
||||||
|
state: present
|
||||||
|
become: true
|
38
setup/roles/install_package/tasks/main.yml
Normal file
38
setup/roles/install_package/tasks/main.yml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Check if pip is installed
|
||||||
|
shell: "which pip"
|
||||||
|
register: which_pip
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install pip
|
||||||
|
package:
|
||||||
|
name: python-pip
|
||||||
|
state: present
|
||||||
|
when: which_pip|failed
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Install rsync
|
||||||
|
package:
|
||||||
|
name: rsync
|
||||||
|
state: present
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Copy cyborg to host
|
||||||
|
synchronize:
|
||||||
|
src: ../../../cyborg/
|
||||||
|
dest: /tmp/cyborg
|
||||||
|
use_ssh_args: yes
|
||||||
|
|
||||||
|
- name: Remove old Cyborg if installed
|
||||||
|
pip:
|
||||||
|
name: cyborg
|
||||||
|
state: absent
|
||||||
|
become: true
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Install Cyborg using pip
|
||||||
|
pip:
|
||||||
|
name: /tmp/cyborg
|
||||||
|
state: present
|
||||||
|
become: true
|
13
setup/roles/template_config/tasks/main.yml
Normal file
13
setup/roles/template_config/tasks/main.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Create cyborg config dir
|
||||||
|
file:
|
||||||
|
path: /etc/cyborg
|
||||||
|
state: directory
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Template Cyborg.conf
|
||||||
|
template:
|
||||||
|
src: cyborg.conf.j2
|
||||||
|
dest: /etc/cyborg/cyborg.conf
|
||||||
|
become: true
|
3
setup/roles/template_config/templates/cyborg.conf.j2
Normal file
3
setup/roles/template_config/templates/cyborg.conf.j2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
connection=mysql+pymysql://cyborg:{{ lookup('password', 'credentials/cyborg/rabbitpassword length=15') }}@overcloud-controller-0.internalapi/nova?read_default_file=/etc/my.cnf.d/tripleo.cnf&read_default_group=tripleo
|
||||||
|
transport_url=rabbit://cyborg:{{ lookup('password', 'credentials/cyborg/rabbitpassword length=15') }}@overcloud-controller-0.internalapi:5672/?ssl=0
|
13
setup/roles/validate_agent/tasks/main.yml
Normal file
13
setup/roles/validate_agent/tasks/main.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Check Agent status
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-agent
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Fail if Agent is not up
|
||||||
|
fail: msg="Cyborg Agent did not start correctly!"
|
||||||
|
when: result.status.ActiveState == "failed"
|
21
setup/roles/validate_api/tasks/main.yml
Normal file
21
setup/roles/validate_api/tasks/main.yml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Check API status
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-api
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Fail if API did not start
|
||||||
|
fail: msg="Cyborg API did not start correctly!"
|
||||||
|
when: result.status.ActiveState == "failed"
|
||||||
|
|
||||||
|
- name: Make a request to the cyborg API endpoint
|
||||||
|
wait_for:
|
||||||
|
host: localhost
|
||||||
|
port: 6666
|
||||||
|
state: started
|
||||||
|
delay: 1
|
||||||
|
timeout: 60
|
13
setup/roles/validate_conductor/tasks/main.yml
Normal file
13
setup/roles/validate_conductor/tasks/main.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Check if Conductor is running
|
||||||
|
service:
|
||||||
|
name: openstack-cyborg-conductor
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
become: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Fail if Conductor is not running
|
||||||
|
fail: msg="Cyborg Conductor did not start correctly!"
|
||||||
|
when: result.status.ActiveState == "failed"
|
Loading…
Reference in New Issue
Block a user