Merge pull request #129 from dreamhost/actionrunner-subclasses

ActionRunner subclasses
This commit is contained in:
Joshua Harlow 2012-03-21 15:52:48 -07:00
commit fc81122b7a
8 changed files with 436 additions and 308 deletions

View File

@ -39,6 +39,7 @@ commands:
stop: service rabbitmq-server stop stop: service rabbitmq-server stop
components: components:
db: db:
action_classes: {}
packages: packages:
- name: mysql - name: mysql
removable: true removable: true
@ -47,6 +48,7 @@ components:
removable: true removable: true
version: 5.5* version: 5.5*
general: general:
action_classes: {}
packages: packages:
- name: curl - name: curl
removable: false removable: false
@ -133,6 +135,7 @@ components:
removable: false removable: false
version: 1.12* version: 1.12*
glance: glance:
action_classes: {}
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -162,6 +165,7 @@ components:
removable: true removable: true
version: 0.5* version: 0.5*
horizon: horizon:
action_classes: {}
packages: packages:
- name: Django - name: Django
removable: true removable: true
@ -215,6 +219,7 @@ components:
removable: true removable: true
version: 0.5* version: 0.5*
keystone: keystone:
action_classes: {}
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -271,6 +276,7 @@ components:
removable: false removable: false
version: 3.7* version: 3.7*
keystone-client: keystone-client:
action_classes: {}
packages: packages:
- name: python-argparse - name: python-argparse
removable: true removable: true
@ -279,13 +285,16 @@ components:
removable: true removable: true
version: 0.5* version: 0.5*
melange: melange:
action_classes: {}
packages: null packages: null
n-api: n-api:
action_classes: {}
packages: packages:
- name: python-dateutil - name: python-dateutil
removable: false removable: false
version: 1.5* version: 1.5*
n-cpu: n-cpu:
action_classes: {}
packages: packages:
- name: iscsi-initiator-utils - name: iscsi-initiator-utils
removable: true removable: true
@ -309,11 +318,13 @@ components:
removable: true removable: true
version: 0.15* version: 0.15*
n-vnc: n-vnc:
action_classes: {}
packages: packages:
- name: numpy - name: numpy
removable: true removable: true
version: 1.6* version: 1.6*
n-vol: n-vol:
action_classes: {}
packages: packages:
- name: iscsi-initiator-utils - name: iscsi-initiator-utils
removable: true removable: true
@ -325,6 +336,7 @@ components:
removable: true removable: true
version: 1.0* version: 1.0*
nova: nova:
action_classes: {}
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -405,6 +417,7 @@ components:
removable: false removable: false
version: 3.7* version: 3.7*
nova-client: nova-client:
action_classes: {}
packages: packages:
- name: python-argparse - name: python-argparse
removable: true removable: true
@ -413,6 +426,7 @@ components:
removable: true removable: true
version: 0.5* version: 0.5*
quantum: quantum:
action_classes: {}
packages: packages:
- name: python-eventlet - name: python-eventlet
removable: true removable: true
@ -436,11 +450,13 @@ components:
removable: true removable: true
version: 1.12* version: 1.12*
quantum-client: quantum-client:
action_classes: {}
packages: packages:
- name: python-gflags - name: python-gflags
removable: true removable: true
version: 1.5* version: 1.5*
quantum-openvswitch: quantum-openvswitch:
action_classes: {}
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -449,6 +465,7 @@ components:
removable: true removable: true
version: 0.7* version: 0.7*
rabbit-mq: rabbit-mq:
action_classes: {}
packages: packages:
- name: rabbitmq-server - name: rabbitmq-server
pre-install: pre-install:
@ -466,6 +483,7 @@ components:
removable: true removable: true
version: 2.6* version: 2.6*
swift: swift:
action_classes: {}
packages: packages:
- name: memcached - name: memcached
removable: true removable: true
@ -496,3 +514,4 @@ components:
version: 3.7* version: 3.7*
packager_name: devstack.packaging.yum:YumPackager packager_name: devstack.packaging.yum:YumPackager
... ...

View File

@ -39,7 +39,11 @@ commands:
stop: service rabbitmq-server stop stop: service rabbitmq-server stop
components: components:
db: db:
action_classes:
install: devstack.distros.rhel6:DBInstaller install: devstack.distros.rhel6:DBInstaller
start: devstack.components.db:DBRuntime
stop: devstack.components.db:DBRuntime
uninstall: devstack.components.db:DBUninstaller
packages: packages:
- name: mysql - name: mysql
removable: true removable: true
@ -47,11 +51,12 @@ components:
- name: mysql-server - name: mysql-server
removable: true removable: true
version: 5.1* version: 5.1*
start: devstack.components.db:DBRuntime
stop: devstack.components.db:DBRuntime
uninstall: devstack.components.db:DBUninstaller
general: general:
action_classes:
install: devstack.components.pkglist:Installer install: devstack.components.pkglist:Installer
start: devstack.component:EmptyRuntime
stop: devstack.component:EmptyRuntime
uninstall: devstack.components.pkglist:Uninstaller
packages: packages:
- name: coreutils - name: coreutils
removable: false removable: false
@ -157,11 +162,12 @@ components:
version: 0.8.0 version: 0.8.0
- name: nose - name: nose
version: 1.1.2 version: 1.1.2
start: devstack.component:EmptyRuntime
stop: devstack.component:EmptyRuntime
uninstall: devstack.components.pkglist:Uninstaller
glance: glance:
action_classes:
install: devstack.components.glance:GlanceInstaller install: devstack.components.glance:GlanceInstaller
start: devstack.components.glance:GlanceRuntime
stop: devstack.components.glance:GlanceRuntime
uninstall: devstack.components.glance:GlanceUninstaller
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -211,11 +217,12 @@ components:
- name: pycrypto - name: pycrypto
options: --upgrade options: --upgrade
version: '2.5' version: '2.5'
start: devstack.components.glance:GlanceRuntime
stop: devstack.components.glance:GlanceRuntime
uninstall: devstack.components.glance:GlanceUninstaller
horizon: horizon:
action_classes:
install: devstack.distros.rhel6:HorizonInstaller install: devstack.distros.rhel6:HorizonInstaller
start: devstack.components.horizon:HorizonRuntime
stop: devstack.components.horizon:HorizonRuntime
uninstall: devstack.components.horizon:HorizonUninstaller
packages: packages:
- name: httpd - name: httpd
removable: true removable: true
@ -273,11 +280,12 @@ components:
version: 1.7.9.3 version: 1.7.9.3
- name: sqlalchemy-migrate - name: sqlalchemy-migrate
version: 0.7.2 version: 0.7.2
start: devstack.components.horizon:HorizonRuntime
stop: devstack.components.horizon:HorizonRuntime
uninstall: devstack.components.horizon:HorizonUninstaller
keystone: keystone:
action_classes:
install: devstack.components.keystone:KeystoneInstaller install: devstack.components.keystone:KeystoneInstaller
start: devstack.components.keystone:KeystoneRuntime
stop: devstack.components.keystone:KeystoneRuntime
uninstall: devstack.components.keystone:KeystoneUninstaller
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -350,11 +358,12 @@ components:
version: '2.5' version: '2.5'
- name: sqlalchemy-migrate - name: sqlalchemy-migrate
version: 0.7.2 version: 0.7.2
start: devstack.components.keystone:KeystoneRuntime
stop: devstack.components.keystone:KeystoneRuntime
uninstall: devstack.components.keystone:KeystoneUninstaller
keystone-client: keystone-client:
action_classes:
install: devstack.components.keystone_client:KeyStoneClientInstaller install: devstack.components.keystone_client:KeyStoneClientInstaller
start: devstack.components.keystone_client:KeyStoneClientRuntime
stop: devstack.components.keystone_client:KeyStoneClientRuntime
uninstall: devstack.components.keystone_client:KeyStoneClientUninstaller
packages: packages:
- meta: - meta:
epel: true epel: true
@ -366,24 +375,27 @@ components:
name: python-prettytable name: python-prettytable
removable: true removable: true
version: 0.5* version: 0.5*
start: devstack.components.keystone_client:KeyStoneClientRuntime
stop: devstack.components.keystone_client:KeyStoneClientRuntime
uninstall: devstack.components.keystone_client:KeyStoneClientUninstaller
melange: melange:
action_classes:
install: devstack.components.melange:MelangeInstaller install: devstack.components.melange:MelangeInstaller
start: devstack.components.melange:MelangeRuntime start: devstack.components.melange:MelangeRuntime
stop: devstack.components.melange:MelangeRuntime stop: devstack.components.melange:MelangeRuntime
uninstall: devstack.components.melange:MelangeUninstaller uninstall: devstack.components.melange:MelangeUninstaller
no-vnc: no-vnc:
action_classes:
install: devstack.components.novnc:NoVNCInstaller install: devstack.components.novnc:NoVNCInstaller
pips:
- name: numpy
version: '1.5'
start: devstack.components.novnc:NoVNCRuntime start: devstack.components.novnc:NoVNCRuntime
stop: devstack.components.novnc:NoVNCRuntime stop: devstack.components.novnc:NoVNCRuntime
uninstall: devstack.components.novnc:NoVNCUninstaller uninstall: devstack.components.novnc:NoVNCUninstaller
pips:
- name: numpy
version: '1.5'
nova: nova:
action_classes:
install: devstack.distros.rhel6:NovaInstaller install: devstack.distros.rhel6:NovaInstaller
start: devstack.components.nova:NovaRuntime
stop: devstack.components.nova:NovaRuntime
uninstall: devstack.components.nova:NovaUninstaller
packages: packages:
- name: MySQL-python - name: MySQL-python
removable: true removable: true
@ -498,8 +510,6 @@ components:
version: '2.5' version: '2.5'
- name: sqlalchemy-migrate - name: sqlalchemy-migrate
version: 0.7.2 version: 0.7.2
start: devstack.components.nova:NovaRuntime
stop: devstack.components.nova:NovaRuntime
subsystems: subsystems:
api: api:
packages: packages:
@ -549,9 +559,12 @@ components:
- name: scsi-target-utils - name: scsi-target-utils
removable: true removable: true
version: 1.0* version: 1.0*
uninstall: devstack.components.nova:NovaUninstaller
nova-client: nova-client:
action_classes:
install: devstack.components.nova_client:NovaClientInstaller install: devstack.components.nova_client:NovaClientInstaller
start: devstack.components.nova_client:NovaClientRuntime
stop: devstack.components.nova_client:NovaClientRuntime
uninstall: devstack.components.nova_client:NovaClientUninstaller
packages: packages:
- meta: - meta:
epel: true epel: true
@ -563,11 +576,12 @@ components:
name: python-prettytable name: python-prettytable
removable: true removable: true
version: 0.5* version: 0.5*
start: devstack.components.nova_client:NovaClientRuntime
stop: devstack.components.nova_client:NovaClientRuntime
uninstall: devstack.components.nova_client:NovaClientUninstaller
quantum: quantum:
action_classes:
install: devstack.components.quantum:QuantumInstaller install: devstack.components.quantum:QuantumInstaller
start: devstack.components.quantum:QuantumRuntime
stop: devstack.components.quantum:QuantumRuntime
uninstall: devstack.components.quantum:QuantumUninstaller
packages: packages:
- name: libxml2-python - name: libxml2-python
removable: false removable: false
@ -600,22 +614,24 @@ components:
version: 0.7.5 version: 0.7.5
- name: sqlalchemy-migrate - name: sqlalchemy-migrate
version: 0.7.2 version: 0.7.2
start: devstack.components.quantum:QuantumRuntime
stop: devstack.components.quantum:QuantumRuntime
uninstall: devstack.components.quantum:QuantumUninstaller
quantum-client: quantum-client:
action_classes:
install: devstack.components.quantum_client:QuantumClientInstaller install: devstack.components.quantum_client:QuantumClientInstaller
start: devstack.components.quantum_client:QuantumClientRuntime
stop: devstack.components.quantum_client:QuantumClientRuntime
uninstall: devstack.components.quantum_client:QuantumClientUninstaller
packages: packages:
- meta: - meta:
epel: true epel: true
name: python-gflags name: python-gflags
removable: true removable: true
version: 1.4* version: 1.4*
start: devstack.components.quantum_client:QuantumClientRuntime
stop: devstack.components.quantum_client:QuantumClientRuntime
uninstall: devstack.components.quantum_client:QuantumClientUninstaller
rabbit-mq: rabbit-mq:
action_classes:
install: devstack.components.rabbit:RabbitInstaller install: devstack.components.rabbit:RabbitInstaller
start: devstack.components.rabbit:RabbitRuntime
stop: devstack.components.rabbit:RabbitRuntime
uninstall: devstack.components.rabbit:RabbitUninstaller
packages: packages:
- meta: - meta:
epel: true epel: true
@ -635,10 +651,8 @@ components:
run_as_root: true run_as_root: true
removable: true removable: true
version: 2.6* version: 2.6*
start: devstack.components.rabbit:RabbitRuntime
stop: devstack.components.rabbit:RabbitRuntime
uninstall: devstack.components.rabbit:RabbitUninstaller
swift: swift:
action_classes:
install: devstack.components.swift:SwiftInstaller install: devstack.components.swift:SwiftInstaller
start: devstack.components.swift:SwiftRuntime start: devstack.components.swift:SwiftRuntime
stop: devstack.components.swift:SwiftRuntime stop: devstack.components.swift:SwiftRuntime

View File

@ -43,7 +43,11 @@ commands:
components: components:
db: db:
action_classes:
install: devstack.distros.oneiric:DBInstaller install: devstack.distros.oneiric:DBInstaller
start: devstack.components.db:DBRuntime
stop: devstack.components.db:DBRuntime
uninstall: devstack.components.db:DBUninstaller
packages: packages:
- name: mysql-client-5.1 - name: mysql-client-5.1
removable: true removable: true
@ -66,11 +70,12 @@ components:
- mysql-server-5.1 mysql-server/start_on_boot boolean %BOOT_START% - mysql-server-5.1 mysql-server/start_on_boot boolean %BOOT_START%
removable: true removable: true
version: 5.1* version: 5.1*
start: devstack.components.db:DBRuntime
stop: devstack.components.db:DBRuntime
uninstall: devstack.components.db:DBUninstaller
general: general:
action_classes:
install: devstack.components.pkglist:Installer install: devstack.components.pkglist:Installer
start: devstack.component:EmptyRuntime
stop: devstack.component:EmptyRuntime
uninstall: devstack.components.pkglist:Uninstaller
packages: packages:
- name: curl - name: curl
removable: false removable: false
@ -150,11 +155,12 @@ components:
pips: pips:
- name: mock - name: mock
version: 0.8.0 version: 0.8.0
start: devstack.component:EmptyRuntime
stop: devstack.component:EmptyRuntime
uninstall: devstack.components.pkglist:Uninstaller
glance: glance:
action_classes:
install: devstack.components.glance:GlanceInstaller install: devstack.components.glance:GlanceInstaller
start: devstack.components.glance:GlanceRuntime
stop: devstack.components.glance:GlanceRuntime
uninstall: devstack.components.glance:GlanceUninstaller
packages: packages:
- name: python-eventlet - name: python-eventlet
removable: true removable: true
@ -192,11 +198,12 @@ components:
pips: pips:
- name: iso8601 - name: iso8601
version: 0.1.4 version: 0.1.4
start: devstack.components.glance:GlanceRuntime
stop: devstack.components.glance:GlanceRuntime
uninstall: devstack.components.glance:GlanceUninstaller
horizon: horizon:
action_classes:
install: devstack.components.horizon:HorizonInstaller install: devstack.components.horizon:HorizonInstaller
start: devstack.components.horizon:HorizonRuntime
stop: devstack.components.horizon:HorizonRuntime
uninstall: devstack.components.horizon:HorizonUninstaller
packages: packages:
- name: apache2 - name: apache2
removable: true removable: true
@ -265,11 +272,12 @@ components:
version: 2.3 version: 2.3
- name: python-cloudfiles - name: python-cloudfiles
version: 1.7.9.3 version: 1.7.9.3
start: devstack.components.horizon:HorizonRuntime
stop: devstack.components.horizon:HorizonRuntime
uninstall: devstack.components.horizon:HorizonUninstaller
keystone: keystone:
action_classes:
install: devstack.components.keystone:KeystoneInstaller install: devstack.components.keystone:KeystoneInstaller
start: devstack.components.keystone:KeystoneRuntime
stop: devstack.components.keystone:KeystoneRuntime
uninstall: devstack.components.keystone:KeystoneUninstaller
packages: packages:
- name: libldap2-dev - name: libldap2-dev
removable: true removable: true
@ -328,11 +336,12 @@ components:
pips: pips:
- name: passlib - name: passlib
version: 1.5.3 version: 1.5.3
start: devstack.components.keystone:KeystoneRuntime
stop: devstack.components.keystone:KeystoneRuntime
uninstall: devstack.components.keystone:KeystoneUninstaller
keystone-client: keystone-client:
action_classes:
install: devstack.components.keystone_client:KeyStoneClientInstaller install: devstack.components.keystone_client:KeyStoneClientInstaller
start: devstack.components.keystone_client:KeyStoneClientRuntime
stop: devstack.components.keystone_client:KeyStoneClientRuntime
uninstall: devstack.components.keystone_client:KeyStoneClientUninstaller
packages: packages:
- name: python-argparse - name: python-argparse
removable: true removable: true
@ -340,11 +349,12 @@ components:
- name: python-prettytable - name: python-prettytable
removable: true removable: true
version: 0.5* version: 0.5*
start: devstack.components.keystone_client:KeyStoneClientRuntime
stop: devstack.components.keystone_client:KeyStoneClientRuntime
uninstall: devstack.components.keystone_client:KeyStoneClientUninstaller
melange: melange:
action_classes:
install: devstack.components.melange:MelangeInstaller install: devstack.components.melange:MelangeInstaller
start: devstack.components.melange:MelangeRuntime
stop: devstack.components.melange:MelangeRuntime
uninstall: devstack.components.melange:MelangeUninstaller
packages: packages:
- name: python-eventlet - name: python-eventlet
removable: true removable: true
@ -370,20 +380,22 @@ components:
- name: python-webob - name: python-webob
removable: true removable: true
version: 1.0* version: 1.0*
start: devstack.components.melange:MelangeRuntime
stop: devstack.components.melange:MelangeRuntime
uninstall: devstack.components.melange:MelangeUninstaller
no-vnc: no-vnc:
action_classes:
install: devstack.components.novnc:NoVNCInstaller install: devstack.components.novnc:NoVNCInstaller
start: devstack.components.novnc:NoVNCRuntime
stop: devstack.components.novnc:NoVNCRuntime
uninstall: devstack.components.novnc:NoVNCUninstaller
packages: packages:
- name: python-numpy - name: python-numpy
removable: true removable: true
version: 1:1.5* version: 1:1.5*
start: devstack.components.novnc:NoVNCRuntime
stop: devstack.components.novnc:NoVNCRuntime
uninstall: devstack.components.novnc:NoVNCUninstaller
nova: nova:
action_classes:
install: devstack.components.nova:NovaInstaller install: devstack.components.nova:NovaInstaller
start: devstack.components.nova:NovaRuntime
stop: devstack.components.nova:NovaRuntime
uninstall: devstack.components.nova:NovaUninstaller
packages: packages:
- name: dnsmasq-base - name: dnsmasq-base
removable: true removable: true
@ -484,8 +496,6 @@ components:
pips: pips:
- name: iso8601 - name: iso8601
version: 0.1.4 version: 0.1.4
start: devstack.components.nova:NovaRuntime
stop: devstack.components.nova:NovaRuntime
subsystems: subsystems:
api: api:
packages: packages:
@ -529,9 +539,12 @@ components:
- name: tgt - name: tgt
removable: true removable: true
version: 1:1* version: 1:1*
uninstall: devstack.components.nova:NovaUninstaller
nova-client: nova-client:
action_classes:
install: devstack.components.nova_client:NovaClientInstaller install: devstack.components.nova_client:NovaClientInstaller
start: devstack.components.nova_client:NovaClientRuntime
stop: devstack.components.nova_client:NovaClientRuntime
uninstall: devstack.components.nova_client:NovaClientUninstaller
packages: packages:
- name: python-argparse - name: python-argparse
removable: true removable: true
@ -539,11 +552,12 @@ components:
- name: python-prettytable - name: python-prettytable
removable: true removable: true
version: 0.5* version: 0.5*
start: devstack.components.nova_client:NovaClientRuntime
stop: devstack.components.nova_client:NovaClientRuntime
uninstall: devstack.components.nova_client:NovaClientUninstaller
quantum: quantum:
action_classes:
install: devstack.components.quantum:QuantumInstaller install: devstack.components.quantum:QuantumInstaller
start: devstack.components.quantum:QuantumRuntime
stop: devstack.components.quantum:QuantumRuntime
uninstall: devstack.components.quantum:QuantumUninstaller
packages: packages:
- name: python-eventlet - name: python-eventlet
removable: true removable: true
@ -566,8 +580,6 @@ components:
- name: python-routes - name: python-routes
removable: true removable: true
version: 1.12* version: 1.12*
start: devstack.components.quantum:QuantumRuntime
stop: devstack.components.quantum:QuantumRuntime
subsystems: subsystems:
openvswitch: openvswitch:
packages: packages:
@ -583,27 +595,32 @@ components:
- name: python-sqlalchemy - name: python-sqlalchemy
removable: true removable: true
version: 0.6* version: 0.6*
uninstall: devstack.components.quantum:QuantumUninstaller
quantum-client: quantum-client:
action_classes:
install: devstack.components.quantum_client:QuantumClientInstaller install: devstack.components.quantum_client:QuantumClientInstaller
start: devstack.components.quantum_client:QuantumClientRuntime
stop: devstack.components.quantum_client:QuantumClientRuntime
uninstall: devstack.components.quantum_client:QuantumClientUninstaller
packages: packages:
- name: python-gflags - name: python-gflags
removable: true removable: true
version: 1.5* version: 1.5*
start: devstack.components.quantum_client:QuantumClientRuntime
stop: devstack.components.quantum_client:QuantumClientRuntime
uninstall: devstack.components.quantum_client:QuantumClientUninstaller
rabbit-mq: rabbit-mq:
action_classes:
install: devstack.components.rabbit:RabbitInstaller install: devstack.components.rabbit:RabbitInstaller
start: devstack.components.rabbit:RabbitRuntime
stop: devstack.components.rabbit:RabbitRuntime
uninstall: devstack.components.rabbit:RabbitUninstaller
packages: packages:
- name: rabbitmq-server - name: rabbitmq-server
removable: true removable: true
version: 2.5* version: 2.5*
start: devstack.components.rabbit:RabbitRuntime
stop: devstack.components.rabbit:RabbitRuntime
uninstall: devstack.components.rabbit:RabbitUninstaller
swift: swift:
action_classes:
install: devstack.components.swift:SwiftInstaller install: devstack.components.swift:SwiftInstaller
start: devstack.components.swift:SwiftRuntime
stop: devstack.components.swift:SwiftRuntime
uninstall: devstack.components.swift:SwiftUninstaller
packages: packages:
- name: memcached - name: memcached
removable: true removable: true
@ -635,8 +652,5 @@ components:
- name: xfsprogs - name: xfsprogs
removable: true removable: true
version: 3.1* version: 3.1*
start: devstack.components.swift:SwiftRuntime
stop: devstack.components.swift:SwiftRuntime
uninstall: devstack.components.swift:SwiftUninstaller
... ...

View File

@ -137,13 +137,11 @@ class Distro(object):
try: try:
# Use a copy instead of the original # Use a copy instead of the original
component_info = dict(self._components[name]) component_info = dict(self._components[name])
entry_point = component_info[action] entry_point = component_info['action_classes'][action]
cls = importer.import_entry_point(entry_point) cls = importer.import_entry_point(entry_point)
# Knock all action class info (and any other keys) # Remove action class info
key_deletions = [action] + settings.ACTIONS if 'action_classes' in component_info:
for k in key_deletions: del component_info['action_classes']
if k in component_info:
del component_info[k]
return (cls, component_info) return (cls, component_info)
except KeyError: except KeyError:
raise RuntimeError('No class configured to %s %s on %s' % raise RuntimeError('No class configured to %s %s on %s' %

View File

@ -17,6 +17,7 @@
from optparse import IndentedHelpFormatter from optparse import IndentedHelpFormatter
from optparse import OptionParser, OptionGroup from optparse import OptionParser, OptionGroup
from devstack.progs import actions
from devstack import log as logging from devstack import log as logging
from devstack import settings from devstack import settings
from devstack import version from devstack import version
@ -64,7 +65,7 @@ def parse():
type="string", type="string",
dest="action", dest="action",
metavar="ACTION", metavar="ACTION",
help="required action to perform: %s" % (_format_list(settings.ACTIONS))) help="required action to perform: %s" % (_format_list(actions.get_action_names())))
base_group.add_option("-d", "--directory", base_group.add_option("-d", "--directory",
action="store", action="store",
type="string", type="string",

View File

@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License.. # under the License..
import abc
from devstack import env_rc from devstack import env_rc
from devstack import exceptions as excp from devstack import exceptions as excp
from devstack import log as logging from devstack import log as logging
@ -22,153 +24,66 @@ from devstack import shell as sh
LOG = logging.getLogger("devstack.progs.actions") LOG = logging.getLogger("devstack.progs.actions")
# For actions in this list we will reverse the component order
REVERSE_ACTIONS = [settings.UNINSTALL, settings.STOP]
# For these actions we will attempt to make an rc file if it does not exist
RC_FILE_MAKE_ACTIONS = [settings.INSTALL]
# The order of which uninstalls happen + message of what is happening
# (before and after)
UNINSTALL_ORDERING = [
(
"Unconfiguring {name}.",
(lambda instance: (instance.unconfigure())),
None,
),
(
"Pre-uninstalling {name}.",
(lambda instance: (instance.pre_uninstall())),
None,
),
(
"Uninstalling {name}.",
(lambda instance: (instance.uninstall())),
None,
),
(
"Post-uninstalling {name}.",
(lambda instance: (instance.post_uninstall())),
None,
),
]
# The order of which starts happen + message of what is happening
# (before and after)
STARTS_ORDERING = [
(
"Configuring runner for {name}.",
(lambda instance: (instance.configure())),
None,
),
(
"Pre-starting {name}.",
(lambda instance: (instance.pre_start())),
None,
),
(
"Starting {name}.",
(lambda instance: (instance.start())),
"Started {result} applications.",
),
(
"Post-starting {name}.",
(lambda instance:(instance.post_start())),
None,
),
]
# The order of which stops happen + message of what is happening
# (before and after)
STOPS_ORDERING = [
(
"Stopping {name}.",
(lambda instance:(instance.stop())),
"Stopped {result} items.",
),
]
# The order of which install happen + message of what is happening
# (before and after)
INSTALL_ORDERING = [
(
"Downloading {name}.",
(lambda instance: (instance.download())),
"Performed {result} downloads.",
),
(
"Configuring {name}.",
(lambda instance: (instance.configure())),
"Configured {result} items.",
),
(
"Pre-installing {name}.",
(lambda instance: (instance.pre_install())),
None,
),
(
"Installing {name}.",
(lambda instance: (instance.install())),
"Finished install of {name} - check {result} for traces of what happened.",
),
(
"Post-installing {name}.",
(lambda instance: (instance.post_install())),
None,
),
]
# Map of action name to action order
ACTION_MP = {
settings.START: STARTS_ORDERING,
settings.STOP: STOPS_ORDERING,
settings.INSTALL: INSTALL_ORDERING,
settings.UNINSTALL: UNINSTALL_ORDERING,
}
# These actions must have there prerequisite action accomplished (if
# determined by the boolean lambda to be needed)
PREQ_ACTIONS = {
settings.START: ((lambda instance: (not instance.is_installed())), settings.INSTALL),
settings.UNINSTALL: ((lambda instance: (instance.is_started())), settings.STOP),
}
class ActionRunner(object): class ActionRunner(object):
def __init__(self, distro, action, __meta__ = abc.ABCMeta
cfg, pw_gen, pkg_manager,
PREREQ = None
def __init__(self,
distro,
cfg,
pw_gen,
pkg_manager,
**kargs): **kargs):
self.distro = distro self.distro = distro
self.action = action
self.cfg = cfg self.cfg = cfg
self.pw_gen = pw_gen self.pw_gen = pw_gen
self.pkg_manager = pkg_manager self.pkg_manager = pkg_manager
self.keep_old = kargs.get('keep_old', False) self.keep_old = kargs.get('keep_old', False)
self.force = kargs.get('force', False) self.force = kargs.get('force', False)
def _apply_reverse(self, action, component_order): @abc.abstractmethod
adjusted_order = list(component_order) def _instance_needs_prereq(self, instance):
if action in REVERSE_ACTIONS: """Determine if the instance will require our prereq to be invoked.
adjusted_order.reverse()
return adjusted_order
def _construct_instances(self, persona, action, root_dir): Return boolean where True means invoke the prereq.
"""
return
@abc.abstractmethod
def _run(self, persona, root_dir, component_order, instances):
"""Run the phases of processing for this action.
Subclasses are expected to override this method to
do something useful.
"""
def _order_components(self, components):
"""Returns the components in the order they should be processed.
"""
# Duplicate the list to avoid problems if it is updated later.
return components[:]
def _construct_instances(self, persona, root_dir):
"""Create component objects for each component in the persona.
"""
components = persona.wanted_components components = persona.wanted_components
desired_subsystems = persona.wanted_subsystems or dict() desired_subsystems = persona.wanted_subsystems or dict()
component_opts = persona.component_options or dict() component_opts = persona.component_options or dict()
instances = dict() instances = dict()
for c in components: for c in components:
(cls, my_info) = self.distro.extract_component(c, action) (cls, my_info) = self.distro.extract_component(c, self.NAME)
LOG.debug("Constructing class %s" % (cls)) LOG.debug("Constructing class %s" % (cls))
cls_kvs = dict() cls_kvs = dict()
cls_kvs['runner'] = self cls_kvs['runner'] = self
cls_kvs['component_dir'] = sh.joinpths(root_dir, c) cls_kvs['component_dir'] = sh.joinpths(root_dir, c)
cls_kvs['subsystem_info'] = my_info.get('subsystems') or dict() cls_kvs['subsystem_info'] = my_info.get('subsystems', {})
cls_kvs['all_instances'] = instances cls_kvs['all_instances'] = instances
cls_kvs['name'] = c cls_kvs['name'] = c
cls_kvs['keep_old'] = self.keep_old cls_kvs['keep_old'] = self.keep_old
cls_kvs['desired_subsystems'] = desired_subsystems.get(c) or set() cls_kvs['desired_subsystems'] = desired_subsystems.get(c, set())
cls_kvs['options'] = component_opts.get(c) or dict() cls_kvs['options'] = component_opts.get(c, {})
# The above is not overrideable... # The above is not overrideable...
for (k, v) in my_info.items(): for (k, v) in my_info.items():
if k not in cls_kvs: if k not in cls_kvs:
@ -183,23 +98,14 @@ class ActionRunner(object):
instance.verify() instance.verify()
def _warm_components(self, component_order, instances): def _warm_components(self, component_order, instances):
LOG.info("Warming up your component configurations (ie so you won't be prompted later)") LOG.info("Warming up component configurations")
for c in component_order: for c in component_order:
instance = instances[c] instance = instances[c]
instance.warm_configs() instance.warm_configs()
def _write_rc_file(self, root_dir): def _run_phase(self, start_msg, functor, end_msg, component_order, instances):
writer = env_rc.RcWriter(self.cfg, self.pw_gen, root_dir) """Run a given 'functor' across all of the components, in order.
if not sh.isfile(settings.OSRC_FN): """
LOG.info("Generating a file at [%s] that will contain your environment settings." % (settings.OSRC_FN))
writer.write(settings.OSRC_FN)
else:
LOG.info("Updating a file at [%s] that contains your environment settings." % (settings.OSRC_FN))
am_upd = writer.update(settings.OSRC_FN)
LOG.info("Updated [%s] settings in rc file [%s]" % (am_upd, settings.OSRC_FN))
def _run_instances(self, action, component_order, instances):
for (start_msg, functor, end_msg) in ACTION_MP[action]:
for c in component_order: for c in component_order:
instance = instances[c] instance = instances[c]
if start_msg: if start_msg:
@ -214,26 +120,217 @@ class ActionRunner(object):
else: else:
raise raise
def _run_action(self, persona, action, root_dir): def _handle_prereq(self, persona, instances, root_dir):
instances = self._construct_instances(persona, action, root_dir) if not self.PREREQ:
if action in PREQ_ACTIONS: return
(check_functor, preq_action) = PREQ_ACTIONS[action] components_needing_prereq = [
checks_passed_components = list() c
for (c, instance) in instances.items(): for (c, instance) in instances.items()
if check_functor(instance): if self._instance_needs_prereq(instance)
checks_passed_components.append(c) ]
if checks_passed_components: if components_needing_prereq:
LOG.info("Activating prerequisite action [%s] requested by (%s) components." LOG.info("Processing prerequisite action [%s] requested by (%s) components.",
% (preq_action, ", ".join(checks_passed_components))) self.PREREQ.NAME, ", ".join(components_needing_prereq))
self._run_action(persona, preq_action, root_dir) prereq = self.PREREQ(self.distro,
component_order = self._apply_reverse(action, persona.wanted_components) self.cfg,
LOG.info("Activating components [%s] (in that order) for action [%s]" % self.pw_gen,
("->".join(component_order), action)) self.pkg_manager,
self._verify_components(component_order, instances) keep_old=self.keep_old,
self._warm_components(component_order, instances) force=self.force,
if action in RC_FILE_MAKE_ACTIONS: )
self._write_rc_file(root_dir) prereq.run(persona, root_dir)
self._run_instances(action, component_order, instances)
def run(self, persona, root_dir): def run(self, persona, root_dir):
self._run_action(persona, self.action, root_dir) instances = self._construct_instances(persona, root_dir)
self._handle_prereq(persona, instances, root_dir)
component_order = self._order_components(persona.wanted_components)
LOG.info("Processing components [%s] (in that order) for action [%s]",
"->".join(component_order), self.NAME)
self._verify_components(component_order, instances)
self._warm_components(component_order, instances)
self._run(persona, root_dir, component_order, instances)
return
class InstallRunner(ActionRunner):
NAME = 'install'
def _instance_needs_prereq(self, instance):
return False
def _write_rc_file(self, root_dir):
writer = env_rc.RcWriter(self.cfg, self.pw_gen, root_dir)
if not sh.isfile(settings.OSRC_FN):
LOG.info("Generating a file at [%s] that will contain your environment settings.",
settings.OSRC_FN)
writer.write(settings.OSRC_FN)
else:
LOG.info("Updating a file at [%s] that contains your environment settings.",
settings.OSRC_FN)
am_upd = writer.update(settings.OSRC_FN)
LOG.info("Updated [%s] settings in rc file [%s]",
am_upd, settings.OSRC_FN)
def _run(self, persona, root_dir, component_order, instances):
self._write_rc_file(root_dir)
self._run_phase(
'Downloading {name}',
lambda i: i.download(),
"Performed {result} downloads.",
component_order,
instances,
)
self._run_phase(
'Configuring {name}',
lambda i: i.configure(),
"Configured {result} items.",
component_order,
instances,
)
self._run_phase(
'Pre-installing {name}',
lambda i: i.pre_install(),
None,
component_order,
instances,
)
self._run_phase(
'Installing {name}',
lambda i: i.install(),
"Finished install of {name} - check {result} for traces of what happened.",
component_order,
instances,
)
self._run_phase(
'Post-installing {name}',
lambda i: i.post_install(),
None,
component_order,
instances,
)
class StartRunner(ActionRunner):
NAME = 'start'
PREREQ = InstallRunner
def _instance_needs_prereq(self, instance):
return not instance.is_installed()
def _run(self, persona, root_dir, component_order, instances):
self._run_phase(
'Configuring runner for {name}',
lambda i: i.configure(),
None,
component_order,
instances,
)
self._run_phase(
'Pre-starting {name}',
lambda i: i.pre_start(),
None,
component_order,
instances,
)
self._run_phase(
'Starting {name}',
lambda i: i.start(),
"Started {result} applications.",
component_order,
instances,
)
self._run_phase(
'Post-starting {name}',
lambda i: i.post_start(),
None,
component_order,
instances,
)
class StopRunner(ActionRunner):
NAME = 'stop'
def _instance_needs_prereq(self, instance):
return False
def _order_components(self, components):
components = super(StopRunner, self)._order_components(components)
components.reverse()
return components
def _run(self, persona, root_dir, component_order, instances):
self._run_phase(
'Stopping {name}',
lambda i: i.stop(),
'Stopped {result} items',
component_order,
instances,
)
class UninstallRunner(ActionRunner):
NAME = 'uninstall'
PREREQ = StopRunner
def _instance_needs_prereq(self, instance):
return instance.is_started()
def _order_components(self, components):
components = super(UninstallRunner, self)._order_components(components)
components.reverse()
return components
def _run(self, persona, root_dir, component_order, instances):
self._run_phase(
'Unconfiguring {name}',
lambda i: i.unconfigure(),
None,
component_order,
instances,
)
self._run_phase(
'Pre-uninstalling {name}',
lambda i: i.pre_uninstall(),
None,
component_order,
instances,
)
self._run_phase(
'Uninstalling {name}',
lambda i: i.uninstall(),
None,
component_order,
instances,
)
self._run_phase(
'Post-uninstalling {name}',
lambda i: i.post_uninstall(),
None,
component_order,
instances,
)
_NAMES_TO_RUNNER = {
'install': InstallRunner,
'uninstall': UninstallRunner,
'start': StartRunner,
'stop': StopRunner,
}
def get_action_names():
"""Returns a list of the available action names.
"""
return sorted(_NAMES_TO_RUNNER.keys())
def get_runner_factory(action):
"""Given an action name, look up the factory for that action runner.
"""
try:
return _NAMES_TO_RUNNER[action]
except KeyError:
raise ValueError('Unrecognized action %s' % action)

View File

@ -47,14 +47,6 @@ RC_FN_TEMPL = "os-%s.rc"
LOCALRC_FN = RC_FN_TEMPL % ('local') LOCALRC_FN = RC_FN_TEMPL % ('local')
OSRC_FN = RC_FN_TEMPL % ('core') OSRC_FN = RC_FN_TEMPL % ('core')
# Program
# actions
INSTALL = "install"
UNINSTALL = "uninstall"
START = "start"
STOP = "stop"
ACTIONS = [INSTALL, UNINSTALL, START, STOP]
# Where the configs and templates should be at. # Where the configs and templates should be at.
STACK_BIN_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) STACK_BIN_DIR = os.path.abspath(os.path.dirname(sys.argv[0]))
STACK_CONFIG_DIR = os.path.join(STACK_BIN_DIR, "conf") STACK_CONFIG_DIR = os.path.join(STACK_BIN_DIR, "conf")

19
stack
View File

@ -39,15 +39,6 @@ from devstack.progs import actions
LOG = logging.getLogger("devstack.stack") LOG = logging.getLogger("devstack.stack")
# This is used to map an action to a useful string for
# the welcome display
_WELCOME_MAP = {
settings.INSTALL: "INSTALLER",
settings.UNINSTALL: "UNINSTALLER",
settings.START: "STARTER",
settings.STOP: "STOPPER",
}
_CFG_GROUPS = { _CFG_GROUPS = {
cfg_helpers.make_id('passwords', None): 'Passwords', cfg_helpers.make_id('passwords', None): 'Passwords',
cfg_helpers.make_id('db', None): 'Database info', cfg_helpers.make_id('db', None): 'Database info',
@ -116,7 +107,7 @@ def setup_root(root_dir):
def run(args): def run(args):
action = args.pop("action", '').strip().lower() action = args.pop("action", '').strip().lower()
if not (action in settings.ACTIONS): if action not in actions.get_action_names():
print(utils.color_text("No valid action specified!", "red")) print(utils.color_text("No valid action specified!", "red"))
return False return False
@ -139,7 +130,7 @@ def run(args):
persona_fn = sh.abspth(persona_fn) persona_fn = sh.abspth(persona_fn)
# Welcome! # Welcome!
(repeat_string, line_max_len) = utils.welcome(_WELCOME_MAP.get(action)) (repeat_string, line_max_len) = utils.welcome(action.upper())
print(utils.center_text("Action Runner", repeat_string, line_max_len)) print(utils.center_text("Action Runner", repeat_string, line_max_len))
# !! # !!
@ -162,8 +153,10 @@ def run(args):
pkg_cls = dist.get_packager_factory() pkg_cls = dist.get_packager_factory()
pkg_manager = pkg_cls(dist, args.get('keep_old', False)) pkg_manager = pkg_cls(dist, args.get('keep_old', False))
runner = actions.ActionRunner(dist, action, runner_factory = actions.get_runner_factory(action)
config, pw_gen, runner = runner_factory(dist,
config,
pw_gen,
pkg_manager, pkg_manager,
**args) **args)