def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return zproxy = ctx.getTopService() commit = False if zproxy.startup.startswith('redis-server'): zproxy.startup = "/bin/supervisord -n -c /etc/zproxy/zproxy_supervisor.conf" zsc = sm.ConfigFile(name='/etc/zproxy/zproxy_supervisor.conf', filename='/etc/zproxy/zproxy_supervisor.conf', owner='zenoss:zenoss', permissions='644', content=zproxy_supervisord_conf) zproxy.configFiles.append(zsc) zproxy.originalConfigs.append(zsc) commit = True if commit: ctx.commit()
def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return zentraps = filter(lambda s: s.name == "zentrap", ctx.services) log.info("Found %i services named 'zentrap'." % len(zentraps)) cfFilter = sm.ConfigFile ( name = "/opt/zenoss/etc/zentrap.filter.conf", filename = "/opt/zenoss/etc/zentrap.filter.conf", owner = "zenoss:zenoss", permissions = "0664", content = open(os.path.join(os.path.dirname(__file__), "config-files", "zentrap.filter.conf"), 'r').read() ) for zentrap in zentraps: # First update zentrap.conf. cf = filter(lambda f: f.name == "/opt/zenoss/etc/zentrap.conf", zentrap.originalConfigs)[0] cf.content = open(os.path.join(os.path.dirname(__file__), "config-files", "zentrap.conf"), 'r').read() log.info("Updated '/opt/zenoss/etc/zentrap.conf' contents.") # Now add zentrap.filter.conf. zentrap.originalConfigs.append(cfFilter) log.info("Added '%s'." % cfFilter.name) # Commit our changes. ctx.commit()
def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return updated = False global_conf = sm.ConfigFile( name="/opt/zenoss/etc/global.conf", filename="/opt/zenoss/etc/global.conf", owner="zenoss:zenoss", permissions="660", content="# Generated by serviced\n{{range $k,$v:=contextFilter . \"global.conf.\"}}{{$k}} {{$v}}\n{{end}}" ) mariadbs = filter(lambda s: s.name in ["mariadb-model", "mariadb-events"], ctx.services) for svc in mariadbs: if not [cfg for cfg in svc.originalConfigs if cfg.name == global_conf.name]: svc.originalConfigs.append(global_conf) updated = True log.info("Updated %s service", svc.name) if not [cfg for cfg in svc.configFiles if cfg.name == global_conf.name]: svc.configFiles.append(global_conf) updated = True log.info("Updated %s service", svc.name) if updated: ctx.commit()
def _addConfig(self, service, configfile, content, cfg_kind): new_config = sm.ConfigFile(name=configfile, filename=configfile, owner="zenoss:zenoss", permissions="0664", content=content) cfg_kind.append(new_config) self.commit = True
class addOpenTSDBLogbackConfig(Migrate.Step): """ Set Editable Logback configuration file for OpenTSDB. See ZEN-27916 """ version = Migrate.Version(116, 0, 0) def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return commit = False services = filter(lambda s: "opentsdb" in ctx.getServicePath(s), ctx.services) log.info("Found %i services with 'opentsdb' in their service path." % len(services)) services = filter(lambda s: "/opt/zenoss/etc/opentsdb/opentsdb.conf" in [i.name for i in s.originalConfigs], services) log.info("Of those, %i services use /opt/zenoss/etc/opentsdb/opentsdb.conf." % len(services)) with open(zenPath('Products/ZenModel/migrate/data/opentsdb-logback.xml')) as fcontent: try: content = fcontent.read() except Exception, e: log.error("Error reading logback configuration file: {}".format(e)) return def equal(this, that): return this.name == that.name and this.filename == that.filename and this.owner == that.owner and this.permissions == that.permissions and this.content == that.content for service in services: newConfig = sm.ConfigFile( name="/opt/opentsdb/src/logback.xml", filename="/opt/opentsdb/src/logback.xml", owner="root:root", permissions="0664", content=content ) # If there's a config with the same name but is different from # the new config, overwrite it. if all(not equal(config, newConfig) for config in service.originalConfigs): service.originalConfigs.append(newConfig) log.info("Adding a configuration to OriginalConfigs of %s", service.name) commit = True # Add this config only if there's no config with the same name. # If there is such config, honor it. if all(not equal(config, newConfig) for config in service.configFiles): service.configFiles.append(newConfig) log.info("Adding a configuration to ConfigFiles of %s", service.name) commit = True log.info("Configuration added for OpenTSDB services") if commit: ctx.commit()
def _addConfig(self, service, configFile, content): config = self._getConfigs(service, configFile) if config: log.info("Service %s configFiles already has %s",service.name, config.name) else: new_config = sm.ConfigFile( name=configFile, filename=configFile, owner="zenoss:zenoss", permissions="0664", content=content ) service.configFiles.append(new_config) log.info("Added %s config to service %s configFiles",new_config.name, service.name)
def test_configfiles_replace(self): """ Tests completely replacing the configFiles list. """ ctx = sm.ServiceContext(INFILENAME) svc = filter(lambda x: x.description == "Zope server", ctx.services)[0] svc.configFiles = [ sm.ConfigFile("foo", "bar", "baz", "777", "foo bar baz"), sm.ConfigFile("baz", "foo", "bar", "111", "baz foo bar") ] ctx.commit(OUTFILENAME) ctx = sm.ServiceContext(OUTFILENAME) svc = filter(lambda x: x.description == "Zope server", ctx.services)[0] if not "foo" in [cf.name for cf in svc.configFiles]: raise ValueError("Failed to alter config files.") if not "baz" in [cf.name for cf in svc.configFiles]: raise ValueError("Failed to alter config files.") for cf in svc.configFiles: if cf.name == "foo": self.assertEqual(cf.content, "foo bar baz") if cf.name == "baz": self.assertEqual(cf.permissions, "111") self.assertEqual(len(svc.configFiles), 2)
def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return memcacheds = filter(lambda s: s.name == "memcached", ctx.services) log.info("Found %i services named 'memcached'" % len(memcacheds)) if not memcacheds: log.info("Couldn't find memcached service, skipping.") return commit = False for memcached in memcacheds: answering = filter(lambda hc: hc.name == 'answering', memcached.healthChecks) if answering: answering[ 0].script = "{ echo stats; sleep 1; } | nc 127.0.0.1 11211 | grep -q uptime" commit = True log.info("Updated 'answering' healthcheck.") else: log.info("Could not find 'answering' healthcheck to update.") # Create /etc/sysconfig/memcached if it doesn't exist esm_content = """\ PORT="11211" USER="******" MAXCONN="1024" CACHESIZE="{{.RAMCommitment}}" OPTIONS="" """ e_s_memcached = sm.ConfigFile( name="/etc/sysconfig/memcached", filename="/etc/sysconfig/memcached", owner="zenoss:zenoss", permissions="0664", content=esm_content, ) if '/etc/sysconfig/memcached' not in [ cf.name for cf in memcached.originalConfigs ]: memcached.originalConfigs.append(e_s_memcached) log.info("Added '/etc/sysconfig/memcached'") commit = True if commit: ctx.commit()
def test_configfiles_add(self): """ Tests adding config files to an existing list. """ ctx = sm.ServiceContext(INFILENAME) svc = filter(lambda x: x.description == "Zope server", ctx.services)[0] self.assertEqual(len(svc.configFiles), 2) svc.configFiles.append( sm.ConfigFile("foo", "bar", "baz", "777", "foo bar baz")) svc.configFiles.append( sm.ConfigFile("baz", "foo", "bar", "111", "baz foo bar")) ctx.commit(OUTFILENAME) ctx = sm.ServiceContext(OUTFILENAME) svc = filter(lambda x: x.description == "Zope server", ctx.services)[0] if not "foo" in [hc.name for hc in svc.configFiles]: raise ValueError("Failed to alter configFiles.") if not "baz" in [hc.name for hc in svc.configFiles]: raise ValueError("Failed to alter configFiles.") for cf in svc.configFiles: if cf.name == "foo": self.assertEqual(cf.content, "foo bar baz") if cf.name == "baz": self.assertEqual(cf.permissions, "111") self.assertEqual(len(svc.configFiles), 4)
def cutover(self, dmd): log.info("Starting rabbitmq supervisord migration.") try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return content = "[supervisord]\nnodaemon=true\nlogfile = /opt/zenoss/log/supervisord.log\n\n[unix_http_server]\nfile=/tmp/supervisor.sock\n\n[supervisorctl]\nserverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket\n\n[rpcinterface:supervisor]\nsupervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface\n\n[program:rabbitmq]\ncommand=/usr/sbin/rabbitmq-server\nautorestart=true\nautostart=true\nstartsecs=5\npriority=1\n\n[program:rabbitmq_metrics]\ncommand=/usr/bin/python /opt/zenoss/bin/metrics/rabbitstats.py\nautorestart=true\nautostart=true\nstartsecs=5\n\n; logging\nredirect_stderr=true\nstdout_logfile_maxbytes=10MB\nstdout_logfile_backups=10\nstdout_logfile=/opt/zenoss/log/%(program_name)s.log\n" newConfig = sm.ConfigFile( name="/etc/rabbitmq/rabbit_supervisor.conf", filename="/etc/rabbitmq/rabbit_supervisor.conf", owner="root:root", permissions="0664", content=content) rabbit_services = filter(lambda s: s.name == 'RabbitMQ', ctx.services) log.info("Found %i services named 'RabbitMQ'." % len(rabbit_services)) changed = False for rabbit in rabbit_services: log.info("Updating rabbitmq startup command to use supervisord.") rabbit.startup = '/bin/supervisord -n -c /etc/rabbitmq/rabbit_supervisor.conf' if all([ not originalConfig.name == newConfig.name for originalConfig in rabbit.originalConfigs ]): rabbit.originalConfigs.append(newConfig) changed = True log.info("Added supervisord original config file.") if all([ not config.name == newConfig.name for config in rabbit.configFiles ]): rabbit.configFiles.append(newConfig) changed = True log.info("Added supervisord config file.") # Commit our changes. if changed: ctx.commit() log.info("committed changes for rabbitmq supervisord config.")
def updateService(serviceName): changed = False services = filter(lambda s: s.name == serviceName, ctx.services) hm_content = "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements. See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership. The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License. You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# syntax: [prefix].[source|sink].[instance].[options]\n# See javadoc of package-info.java for org.apache.hadoop.metrics2 for details\n\n# sampling period\n*.period=15\n\n# Below are some examples of sinks that could be used\n# to monitor different hbase daemons.\n\nhbase.sink.file-all.class=com.zenoss.hadoop.metrics.ControlCenterSink\nhbase.sink.file-all.includedMetrics=Log\\\\w*,\\\\w*RegionServers\n# hbase.sink.file0.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file0.context=hmaster\n# hbase.sink.file0.filename=master.metrics\n\n# hbase.sink.file1.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file1.context=thrift-one\n# hbase.sink.file1.filename=thrift-one.metrics\n\n# hbase.sink.file2.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file2.context=thrift-two\n# hbase.sink.file2.filename=thrift-one.metrics\n\n# hbase.sink.file3.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file3.context=rest\n# hbase.sink.file3.filename=rest.metrics\n" rs_content = "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements. See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership. The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License. You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# syntax: [prefix].[source|sink].[instance].[options]\n# See javadoc of package-info.java for org.apache.hadoop.metrics2 for details\n\n# sampling period\n*.period=15\n\n# Below are some examples of sinks that could be used\n# to monitor different hbase daemons.\n\nhbase.sink.file-all.class=com.zenoss.hadoop.metrics.ControlCenterSink\nhbase.sink.file-all.includedMetrics=numCallsInGeneralQueue,numCallsIn\\\\w*Queue,\\\\w*QueueLength,\\\\w*Count,\\\\w+RequestCount\n# hbase.sink.file0.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file0.context=hmaster\n# hbase.sink.file0.filename=master.metrics\n\n# hbase.sink.file1.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file1.context=thrift-one\n# hbase.sink.file1.filename=thrift-one.metrics\n\n# hbase.sink.file2.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file2.context=thrift-two\n# hbase.sink.file2.filename=thrift-one.metrics\n\n# hbase.sink.file3.class=org.apache.hadoop.metrics2.sink.FileSink\n# hbase.sink.file3.context=rest\n# hbase.sink.file3.filename=rest.metrics\n" content = hm_content if serviceName == 'HMaster' else rs_content def equal(this, that): return this.name == that.name and this.filename == that.filename and this.owner == that.owner and this.permissions == that.permissions and this.content == that.content for service in services: newConfig = sm.ConfigFile( name="/opt/hbase/conf/hadoop-metrics2-hbase.properties", filename="/opt/hbase/conf/hadoop-metrics2-hbase.properties", owner="hbase:hbase", permissions="0664", content=content) # If there's a config with the same name but is different from # the new config, overwrite it. if all([ not equal(config, newConfig) for config in service.originalConfigs ]): service.originalConfigs.append(newConfig) changed = True log.info("Adding a configuration to OriginalConfigs of %s", service.name) # Add this config only if there's no config with the same name. # If there is such config, honor it. if all([ not config.name == newConfig.name for config in service.configFiles ]): service.configFiles.append(newConfig) changed = True log.info("Adding a configuration to ConfigFiles of %s", service.name) return changed
def cutover(self, dmd): try: ctx = sm.ServiceContext() except sm.ServiceMigrationError: log.info("Couldn't generate service context, skipping.") return content = """\ # Generated by serviced {{range $k,$v:=contextFilter . \"global.conf.\"}}{{$k}} {{$v}}\n{{end}}\ """ global_conf = sm.ConfigFile( name="/opt/zenoss/etc/global.conf", filename="/opt/zenoss/etc/global.conf", owner="zenoss:zenoss", permissions="660", content=content, ) rabbits = filter(lambda s: 'RabbitMQ' in ctx.getServicePath(s), ctx.services) log.info("Found %i services called 'RabbitMQ' in their service path." % len(rabbits)) added = 0 commit = False for rabbit in rabbits: config_names = [f.name for f in rabbit.originalConfigs] if global_conf.name not in config_names: rabbit.originalConfigs.append(global_conf) rabbit.configFiles.append(global_conf) added += 1 commit = True log.info("Added global_conf to %i RabbitMQs." % added) if commit: ctx.commit()
def _addMariaDBConfig(self, service): original, config = self._getConfigs( service, "/etc/mariadb/mariadb_supervisor.conf" ) new_config = sm.ConfigFile( name="/etc/mariadb/mariadb_supervisor.conf", filename="/etc/mariadb/mariadb_supervisor.conf", owner="root:root", permissions="0664", content=_ConfigContent.format( service=service.name, section=service.name.replace("-", "_") ) ) if not original: service.originalConfigs.append(new_config) log.info( "Added %s config to service %s originalConfigs", new_config.name, service.name ) else: log.info( "Service %s originalConfigs already has %s", service.name, new_config.name ) if not config: service.configFiles.append(new_config) log.info( "Added %s config to service %s configFiles", new_config.name, service.name ) else: log.info( "Service %s configFiles already has %s", service.name, new_config.name )
svc.originalConfigs = filter(lambda x: x.name != "/opt/zenoss/etc/global.conf", svc.originalConfigs) # Alter the "/opt/zenoss/etc/zope.conf" config file. zopeconf = filter(lambda x: x.name == "/opt/zenoss/etc/zope.conf", svc.originalConfigs)[0] zopeconf.filename = "zope_config_filename" zopeconf.owner = "foo:bar" zopeconf.permissions = "777" zopeconf.content = "Zope conf contents" # Add a new config file. svc.originalConfigs.append( sm.ConfigFile(name="new configfile name", filename="new configfile filename", owner="new configfile owner", permissions="111", content="new configfile content")) # Alter the instance limits. svc.instanceLimits.minimum = 0 svc.instanceLimits.maximum = 2 svc.instanceLimits.default = 2 # Add the tag "tag". svc.tags.append("tag") # Remove the tag "daemon". svc.tags.remove("daemon") # Alter the version of all services.