Got quantum install + configuration working.

This commit is contained in:
Joshua Harlow 2012-01-25 17:30:40 -08:00
parent 3bb3e275bf
commit bc8d51c1db
10 changed files with 198 additions and 43 deletions

View File

@ -140,7 +140,7 @@ class PkgInstallComponent(ComponentBase):
#ensure directory is there (if not created previously)
self.tracewriter.make_dir(sh.dirname(tgtfn))
#now configure it
LOG.info("Configuring template file %s" % (fn))
LOG.info("Configuring file %s" % (fn))
(sourcefn, contents) = self._get_source_config(fn)
LOG.info("Replacing parameters in file %s" % (sourcefn))
LOG.debug("Replacements = %s" % (parameters))

View File

@ -56,6 +56,7 @@ BASE_ERROR = 'Currently we do not know how to %s for database type [%s]'
#used to make params for booting when started (not always take advantage of...)
BOOLEAN_OUTPUT = {True: 'true', False: 'false'}
class DBUninstaller(comp.PkgUninstallComponent):
def __init__(self, *args, **kargs):
comp.PkgUninstallComponent.__init__(self, TYPE, *args, **kargs)

View File

@ -109,6 +109,7 @@ class GlanceInstaller(comp.PythonInstallComponent):
return parent_result
def _setup_db(self):
LOG.info("Fixing up database named %s", DB_NAME)
db.drop_db(self.cfg, DB_NAME)
db.create_db(self.cfg, DB_NAME)

View File

@ -125,7 +125,7 @@ class HorizonInstaller(comp.PythonInstallComponent):
path = sh.joinpths(self.dash_dir, 'local')
if sh.isdir(path):
(user, group) = self._get_apache_user_group()
LOG.info("Changing ownership (recursively) of %s so that it can be used by %s - %s",
LOG.info("Changing ownership (recursively) of %s so that it can be used by %s - %s",
path, user, group)
uid = sh.getuid(user)
gid = sh.getgid(group)
@ -177,14 +177,14 @@ class HorizonRuntime(comp.EmptyRuntime):
#restart it ?
return self.restart()
else:
sh.execute(*APACHE_START_CMD,
sh.execute(*APACHE_START_CMD,
run_as_root=True)
return 1
def restart(self):
curr_status = self.status()
if curr_status == comp.STATUS_STARTED:
sh.execute(*APACHE_RESTART_CMD,
sh.execute(*APACHE_RESTART_CMD,
run_as_root=True)
return 1
return 0
@ -192,13 +192,13 @@ class HorizonRuntime(comp.EmptyRuntime):
def stop(self):
curr_status = self.status()
if curr_status == comp.STATUS_STARTED:
sh.execute(*APACHE_STOP_CMD,
sh.execute(*APACHE_STOP_CMD,
run_as_root=True)
return 1
return 0
def status(self):
(sysout, _) = sh.execute(*APACHE_STATUS_CMD,
(sysout, _) = sh.execute(*APACHE_STATUS_CMD,
check_exit_code=False)
if sysout.find("is running") != -1:
return comp.STATUS_STARTED

View File

@ -85,6 +85,7 @@ class KeystoneInstaller(comp.PythonInstallComponent):
return list(CONFIGS)
def _setup_db(self):
LOG.info("Fixing up database named %s", DB_NAME)
db.drop_db(self.cfg, DB_NAME)
db.create_db(self.cfg, DB_NAME)

View File

@ -13,47 +13,186 @@
# License for the specific language governing permissions and limitations
# under the License.
import io
from devstack import cfg
from devstack import component as comp
from devstack import log as logging
from devstack import settings
from devstack import shell as sh
from devstack import utils
from devstack.components import db
LOG = logging.getLogger("devstack.components.quantum")
#vswitch pkgs
VSWITCH_PLUGIN = 'openvswitch'
PKG_VSWITCH = "quantum-openvswitch.json"
V_PROVIDER = "quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPlugin"
#config files (some only modified if running as openvswitch
PLUGIN_CONF = "plugins.ini"
PLUGIN_LOC = ['etc']
AGENT_CONF = 'ovs_quantum_plugin.ini'
AGENT_LOC = ["etc", "quantum", "plugins", "openvswitch"]
CONFIG_FILES = [PLUGIN_CONF, AGENT_CONF]
#this db will be dropped and created
DB_NAME = 'ovs_quantum'
#opensvswitch bridge setup/teardown/name commands
OVS_BRIDGE_DEL = ['ovs-vsctl', '--no-wait', '--', '--if-exists', 'del-br', '%OVS_BRIDGE%']
OVS_BRIDGE_ADD = ['ovs-vsctl', '--no-wait', 'add-br', '%OVS_BRIDGE%']
OVS_BRIDGE_EXTERN_ID = ['ovs-vsctl', '--no-wait', 'br-set-external-id', '%OVS_BRIDGE%', 'bridge-id', '%OVS_EXTERNAL_ID%']
#id
TYPE = settings.QUANTUM
#special component options
QUANTUM_SERVICE = 'q-svc'
QUANTUM_AGENT = 'q-agt'
class QuantumUninstaller(object):
class QuantumUninstaller(comp.PkgUninstallComponent):
def __init__(self, *args, **kargs):
pass
def unconfigure(self):
raise NotImplementedError()
def uninstall(self):
raise NotImplementedError()
comp.PkgUninstallComponent.__init__(self, TYPE, *args, **kargs)
class QuantumInstaller(object):
class QuantumInstaller(comp.PkgInstallComponent):
def __init__(self, *args, **kargs):
pass
comp.PkgInstallComponent.__init__(self, TYPE, *args, **kargs)
self.git_loc = self.cfg.get("git", "quantum_repo")
self.git_branch = self.cfg.get("git", "quantum_branch")
self.q_vswitch_agent = False
self.q_vswitch_service = False
plugin = self.cfg.get("quantum", "q_plugin")
if plugin == VSWITCH_PLUGIN:
if len(self.component_opts) == 0:
#default to on if not specified
self.q_vswitch_agent = True
self.q_vswitch_service = True
else:
#only turn on if requested
if QUANTUM_SERVICE in self.component_opts:
self.q_vswitch_service = True
if QUANTUM_AGENT in self.component_opts:
self.q_vswitch_agent = True
def download(self):
raise NotImplementedError()
def _get_download_locations(self):
places = comp.PkgInstallComponent._get_download_locations(self)
places.append({
'uri': self.git_loc,
'branch': self.git_branch,
})
return places
def configure(self):
raise NotImplementedError()
def get_pkglist(self):
if self.q_vswitch_service:
listing_fn = sh.joinpths(settings.STACK_PKG_DIR, PKG_VSWITCH)
return utils.extract_pkg_list([listing_fn], self.distro)
else:
return comp.PkgInstallComponent.get_pkglist(self)
def pre_install(self):
raise NotImplementedError()
def _get_config_files(self):
parent_list = comp.PkgInstallComponent._get_config_files(self)
parent_list.extend(CONFIG_FILES)
return parent_list
def install(self):
raise NotImplementedError()
def _get_target_config_name(self, config_fn):
if config_fn == PLUGIN_CONF:
tgt_loc = [self.appdir] + PLUGIN_LOC + [config_fn]
return sh.joinpths(*tgt_loc)
elif config_fn == AGENT_CONF:
tgt_loc = [self.appdir] + AGENT_LOC + [config_fn]
return sh.joinpths(*tgt_loc)
else:
return comp.PkgInstallComponent._get_target_config_name(self, config_fn)
def _config_adjust(self, contents, config_fn):
if config_fn == PLUGIN_CONF and self.q_vswitch_service:
#need to fix the "Quantum plugin provider module"
newcontents = contents
with io.BytesIO(contents) as stream:
config = cfg.IgnoreMissingConfigParser()
config.readfp(stream)
provider = config.get("PLUGIN", "provider")
if provider and provider != V_PROVIDER:
config.set("PLUGIN", "provider", V_PROVIDER)
with io.BytesIO() as outputstream:
config.write(outputstream)
outputstream.flush()
#TODO can we write to contents here directly?
newcontents = outputstream.getvalue()
return newcontents
elif config_fn == AGENT_CONF and self.q_vswitch_agent:
#Need to adjust the sql connection
newcontents = contents
with io.BytesIO(contents) as stream:
config = cfg.IgnoreMissingConfigParser()
config.readfp(stream)
db_dsn = config.get("DATABASE", "sql_connection")
if db_dsn:
generated_dsn = self.cfg.get_dbdsn(DB_NAME)
if generated_dsn != db_dsn:
config.set("DATABASE", "sql_connection", generated_dsn)
with io.BytesIO() as outputstream:
config.write(outputstream)
outputstream.flush()
#TODO can we write to contents here directly?
newcontents = outputstream.getvalue()
return newcontents
else:
return comp.PkgInstallComponent._config_adjust(self, contents, config_fn)
def _setup_bridge(self):
bridge = self.cfg.get("quantum", "ovs_bridge")
if bridge:
LOG.info("Fixing up ovs bridge named %s", bridge)
external_id = self.cfg.get("quantum", 'ovs_bridge_external_name')
if not external_id:
external_id = bridge
params = dict()
params['OVS_BRIDGE'] = bridge
params['OVS_EXTERNAL_ID'] = external_id
cmds = list()
cmds.append({
'cmd': OVS_BRIDGE_DEL
})
cmds.append({
'cmd': OVS_BRIDGE_ADD
})
cmds.append({
'cmd': OVS_BRIDGE_EXTERN_ID
})
utils.execute_template(*cmds, params=params)
#TODO maybe have a trace that says we did this so that we can remove it on uninstall?
def post_install(self):
raise NotImplementedError()
parent_result = comp.PkgInstallComponent.post_install(self)
if self.q_vswitch_service and settings.DB in self.instances:
self._setup_db()
if self.q_vswitch_agent:
self._setup_bridge()
return parent_result
def _setup_db(self):
LOG.info("Fixing up database named %s", DB_NAME)
db.drop_db(self.cfg, DB_NAME)
db.create_db(self.cfg, DB_NAME)
def _get_source_config(self, config_fn):
if config_fn == PLUGIN_CONF:
srcloc = [self.appdir] + PLUGIN_LOC + [config_fn]
srcfn = sh.joinpths(*srcloc)
contents = sh.load_file(srcfn)
return (srcfn, contents)
elif config_fn == AGENT_CONF:
srcloc = [self.appdir] + AGENT_LOC + [config_fn]
srcfn = sh.joinpths(*srcloc)
contents = sh.load_file(srcfn)
return (srcfn, contents)
else:
return comp.PkgInstallComponent._get_source_config(self, config_fn)
class QuantumRuntime(comp.EmptyRuntime):

View File

@ -46,5 +46,5 @@ def download(storewhere, uri, branch=None):
EXT_REG.match(up.path):
return _gitdownload(storewhere, uri, branch)
else:
msg = "Currently we do not know how to download %s" % (uri)
msg = "Currently we do not know how to download from uri [%s]" % (uri)
raise NotImplementedError(msg)

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
class StackException(Exception):
pass

View File

@ -100,7 +100,9 @@ COMPONENT_DEPENDENCIES = {
SWIFT: [],
NOVA_CLIENT: [],
HORIZON: [KEYSTONE_CLIENT, GLANCE, NOVA_CLIENT, OPENSTACK_X],
QUANTUM: [],
#the db isn't always a dependency (depending on the quantum component to be activated)
#for now assume it is (TODO make it better?)
QUANTUM: [DB],
NOVNC: [],
}
@ -200,7 +202,8 @@ PKG_MAP = {
],
QUANTUM:
[
os.path.join(STACK_PKG_DIR, "quantum.json"),
#quantum figures out its own pkgs
#they will be listed in the quantum component
],
DB:
[

View File

@ -135,17 +135,12 @@ def determine_distro():
return (found_os, plt)
def get_pip_list(distro, component):
LOG.info("Getting pip packages for distro %s and component %s." % (distro, component))
def extract_pip_list(fns, distro):
all_pkgs = dict()
fns = settings.PIP_MAP.get(component)
if fns is None:
return all_pkgs
#load + merge them
for fn in fns:
js = load_json(fn)
distro_pkgs = js.get(distro)
if distro_pkgs and len(distro_pkgs):
if distro_pkgs:
combined = dict(all_pkgs)
for (pkgname, pkginfo) in distro_pkgs.items():
#we currently just overwrite
@ -154,17 +149,21 @@ def get_pip_list(distro, component):
return all_pkgs
def get_pkg_list(distro, component):
LOG.info("Getting packages for distro %s and component %s." % (distro, component))
all_pkgs = dict()
fns = settings.PKG_MAP.get(component)
def get_pip_list(distro, component):
LOG.info("Getting pip packages for distro %s and component %s." % (distro, component))
fns = settings.PIP_MAP.get(component)
if fns is None:
return all_pkgs
#load + merge them
return dict()
else:
return extract_pip_list(fns, distro)
def extract_pkg_list(fns, distro):
all_pkgs = dict()
for fn in fns:
js = load_json(fn)
distro_pkgs = js.get(distro)
if distro_pkgs and len(distro_pkgs):
if distro_pkgs:
combined = dict(all_pkgs)
for (pkgname, pkginfo) in distro_pkgs.items():
if pkgname in all_pkgs.keys():
@ -173,7 +172,8 @@ def get_pkg_list(distro, component):
for (infokey, infovalue) in pkginfo.items():
#this is expected to be a list of cmd actions
#so merge that accordingly
if infokey == settings.PRE_INSTALL or infokey == settings.POST_INSTALL:
if(infokey == settings.PRE_INSTALL or
infokey == settings.POST_INSTALL):
oldinstalllist = oldpkginfo.get(infokey) or []
infovalue = oldinstalllist + infovalue
newpkginfo[infokey] = infovalue
@ -184,6 +184,15 @@ def get_pkg_list(distro, component):
return all_pkgs
def get_pkg_list(distro, component):
LOG.info("Getting packages for distro %s and component %s." % (distro, component))
fns = settings.PKG_MAP.get(component)
if fns is None:
return dict()
else:
return extract_pkg_list(fns, distro)
def joinlinesep(*pieces):
return os.linesep.join(pieces)