for dep_type in need.get(daemon_type, []):
for dd in self.cache.get_daemons_by_type(dep_type):
deps.append(dd.name())
+ if daemon_type == 'prometheus':
+ deps.append(str(self.get_module_option_ex('prometheus', 'server_port', 9283)))
return sorted(deps)
@forall_hosts
slot = slot.assign_name(self.mgr.get_unique_name(
slot.daemon_type,
slot.hostname,
- daemons,
+ [d for d in daemons if d not in daemons_to_remove],
prefix=spec.service_id,
forcename=slot.name,
rank=slot.rank,
# create daemons
daemon_place_fails = []
for slot in slots_to_add:
- # first remove daemon on conflicting port?
- if slot.ports:
+ # first remove daemon with conflicting port or name?
+ if slot.ports or slot.name in [d.name() for d in daemons_to_remove]:
for d in daemons_to_remove:
- if d.hostname != slot.hostname:
+ if (
+ d.hostname != slot.hostname
+ or not (set(d.ports or []) & set(slot.ports))
+ or (d.ip and slot.ip and d.ip != slot.ip)
+ and d.name() != slot.name
+ ):
continue
- if not (set(d.ports or []) & set(slot.ports)):
- continue
- if d.ip and slot.ip and d.ip != slot.ip:
- continue
- self.log.info(
- f'Removing {d.name()} before deploying to {slot} to avoid a port conflict'
- )
+ if d.name() != slot.name:
+ self.log.info(
+ f'Removing {d.name()} before deploying to {slot} to avoid a port or conflict'
+ )
# NOTE: we don't check ok-to-stop here to avoid starvation if
# there is only 1 gateway.
self._remove_daemon(d.name(), d.hostname)
class PrometheusService(CephadmService):
TYPE = 'prometheus'
DEFAULT_SERVICE_PORT = 9095
+ DEFAULT_MGR_PROMETHEUS_PORT = 9283
def config(self, spec: ServiceSpec) -> None:
# make sure module is enabled
# scrape mgrs
mgr_scrape_list = []
mgr_map = self.mgr.get('mgr_map')
- port = None
+ port = cast(int, self.mgr.get_module_option_ex(
+ 'prometheus', 'server_port', self.DEFAULT_MGR_PROMETHEUS_PORT))
+ deps.append(str(port))
t = mgr_map.get('services', {}).get('prometheus', None)
if t:
p_result = urlparse(t)
- t = t.split('/')[2]
- mgr_scrape_list.append(t)
- port = p_result.port or 9283
+ # urlparse .hostname removes '[]' from the hostname in case
+ # of ipv6 addresses so if this is the case then we just
+ # append the brackets when building the final scrape endpoint
+ if '[' in p_result.netloc and ']' in p_result.netloc:
+ mgr_scrape_list.append(f"[{p_result.hostname}]:{port}")
+ else:
+ mgr_scrape_list.append(f"{p_result.hostname}:{port}")
# scan all mgrs to generate deps and to get standbys too.
# assume that they are all on the same port as the active mgr.
for dd in self.mgr.cache.get_daemons_by_service('mgr'):
return __file__
+def get_module_option_ex(_, module, key, default=None):
+ if module == 'prometheus':
+ if key == 'server_port':
+ return 9283
+ return None
+
+
def _run_cephadm(ret):
def foo(s, host, entity, cmd, e, **kwargs):
if cmd == 'gather-facts':
"""
with mock.patch("cephadm.module.CephadmOrchestrator.get_ceph_option", get_ceph_option),\
mock.patch("cephadm.services.osd.RemoveUtil._run_mon_cmd"), \
+ mock.patch('cephadm.module.CephadmOrchestrator.get_module_option_ex', get_module_option_ex),\
mock.patch("cephadm.module.CephadmOrchestrator.get_osdmap"), \
mock.patch("cephadm.module.CephadmOrchestrator.remote"), \
mock.patch('cephadm.offline_watcher.OfflineHostWatcher.run'):
honor_labels: true
static_configs:
- targets:
- - '[::1]:8081'
+ - '[::1]:9283'
- job_name: 'node'
static_configs:
),
Option(
'server_port',
- type='int'
+ type='int',
+ default=DEFAULT_PORT,
+ desc='the port on which the module listens for HTTP requests',
+ runtime=True
),
Option(
'scrape_interval',
return metrics
+ def get_server_addr(self) -> str:
+ """
+ Return the current mgr server IP.
+ """
+ server_addr = cast(str, self.get_localized_module_option('server_addr', get_default_addr()))
+ if server_addr in ['::', '0.0.0.0']:
+ return self.get_mgr_ip()
+ return server_addr
+
+ def config_notify(self) -> None:
+ """
+ This method is called whenever one of our config options is changed.
+ """
+ # https://stackoverflow.com/questions/7254845/change-cherrypy-port-and-restart-web-server
+ # if we omit the line: cherrypy.server.httpserver = None
+ # then the cherrypy server is not restarted correctly
+ self.log.info('Restarting engine...')
+ cherrypy.engine.stop()
+ cherrypy.server.httpserver = None
+ server_port = cast(int, self.get_localized_module_option('server_port', DEFAULT_PORT))
+ self.set_uri(build_url(scheme='http', host=self.get_server_addr(), port=server_port, path='/'))
+ cherrypy.config.update({'server.socket_port': server_port})
+ cherrypy.engine.start()
+ self.log.info('Engine started.')
+
@profile_method()
def get_health(self) -> None:
})
# Publish the URI that others may use to access the service we're
# about to start serving
- if server_addr in ['::', '0.0.0.0']:
- server_addr = self.get_mgr_ip()
- self.set_uri(build_url(scheme='http', host=server_addr, port=server_port, path='/'))
+ self.set_uri(build_url(scheme='http', host=self.get_server_addr(), port=server_port, path='/'))
cherrypy.tree.mount(Root(), "/")
self.log.info('Starting engine...')
# tell metrics collection thread to stop collecting new metrics
self.metrics_thread.stop()
cherrypy.engine.stop()
+ cherrypy.server.httpserver = None
self.log.info('Engine stopped.')
self.shutdown_rbd_stats()
# wait for the metrics collection thread to stop
self.shutdown_event.wait()
self.shutdown_event.clear()
cherrypy.engine.stop()
+ cherrypy.server.httpserver = None
self.log.info('Engine stopped.')
def shutdown(self) -> None: