2 # Copyright 2021 Canonical Ltd.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
16 # For those usages not covered by the Apache License, Version 2.0 please
17 # contact: legal@canonical.com
19 # To get in touch with the maintainers, please contact:
20 # osm-charmers@lists.launchpad.net
23 # pylint: disable=E0213
27 from typing
import NoReturn
29 from ops
.main
import main
31 from opslib
.osm
.charm
import CharmedOsmBase
, RelationsMissing
33 from opslib
.osm
.pod
import (
38 from opslib
.osm
.validator
import (
43 from opslib
.osm
.interfaces
.kafka
import KafkaClient
44 from opslib
.osm
.interfaces
.mongo
import MongoClient
45 from opslib
.osm
.interfaces
.prometheus
import PrometheusClient
48 logger
= logging
.getLogger(__name__
)
53 class ConfigModel(ModelValidator
):
58 database_commonkey
: str
60 openstack_default_granularity
: int
61 global_request_timeout
: int
62 collector_interval
: int
63 evaluator_interval
: int
68 @validator("log_level")
69 def validate_log_level(cls
, v
):
70 if v
not in {"INFO", "DEBUG"}:
71 raise ValueError("value must be INFO or DEBUG")
75 class MonCharm(CharmedOsmBase
):
76 def __init__(self
, *args
) -> NoReturn
:
77 super().__init
__(*args
, oci_image
="image")
79 self
.kafka_client
= KafkaClient(self
, "kafka")
80 self
.framework
.observe(self
.on
["kafka"].relation_changed
, self
.configure_pod
)
81 self
.framework
.observe(self
.on
["kafka"].relation_broken
, self
.configure_pod
)
83 self
.mongodb_client
= MongoClient(self
, "mongodb")
84 self
.framework
.observe(self
.on
["mongodb"].relation_changed
, self
.configure_pod
)
85 self
.framework
.observe(self
.on
["mongodb"].relation_broken
, self
.configure_pod
)
87 self
.prometheus_client
= PrometheusClient(self
, "prometheus")
88 self
.framework
.observe(
89 self
.on
["prometheus"].relation_changed
, self
.configure_pod
91 self
.framework
.observe(
92 self
.on
["prometheus"].relation_broken
, self
.configure_pod
95 def _check_missing_dependencies(self
, config
: ConfigModel
):
96 missing_relations
= []
98 if self
.kafka_client
.is_missing_data_in_unit():
99 missing_relations
.append("kafka")
100 if self
.mongodb_client
.is_missing_data_in_unit():
101 missing_relations
.append("mongodb")
102 if self
.prometheus_client
.is_missing_data_in_app():
103 missing_relations
.append("prometheus")
105 if missing_relations
:
106 raise RelationsMissing(missing_relations
)
108 def build_pod_spec(self
, image_info
):
110 config
= ConfigModel(**dict(self
.config
))
112 self
._check
_missing
_dependencies
(config
)
113 # Create Builder for the PodSpec
114 pod_spec_builder
= PodSpecV3Builder()
116 container_builder
= ContainerV3Builder(self
.app
.name
, image_info
)
117 container_builder
.add_port(name
=self
.app
.name
, port
=PORT
)
118 container_builder
.add_envs(
120 # General configuration
121 "ALLOW_ANONYMOUS_LOGIN": "yes",
122 "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": config
.openstack_default_granularity
,
123 "OSMMON_GLOBAL_REQUEST_TIMEOUT": config
.global_request_timeout
,
124 "OSMMON_GLOBAL_LOGLEVEL": config
.log_level
,
125 "OSMMON_COLLECTOR_INTERVAL": config
.collector_interval
,
126 "OSMMON_EVALUATOR_INTERVAL": config
.evaluator_interval
,
127 # Kafka configuration
128 "OSMMON_MESSAGE_DRIVER": "kafka",
129 "OSMMON_MESSAGE_HOST": self
.kafka_client
.host
,
130 "OSMMON_MESSAGE_PORT": self
.kafka_client
.port
,
131 # Database configuration
132 "OSMMON_DATABASE_DRIVER": "mongo",
133 "OSMMON_DATABASE_URI": self
.mongodb_client
.connection_string
,
134 "OSMMON_DATABASE_COMMONKEY": config
.database_commonkey
,
135 # Prometheus configuration
136 "OSMMON_PROMETHEUS_URL": f
"http://{self.prometheus_client.hostname}:{self.prometheus_client.port}",
138 "OSMMON_VCA_HOST": config
.vca_host
,
139 "OSMMON_VCA_USER": config
.vca_user
,
140 "OSMMON_VCA_SECRET": config
.vca_password
,
141 "OSMMON_VCA_CACERT": config
.vca_cacert
,
142 "OSMMON_GRAFANA_URL": config
.grafana_url
,
143 "OSMMON_GRAFANA_USER": config
.grafana_user
,
144 "OSMMON_GRAFANA_PASSWORD": config
.grafana_password
,
148 container
= container_builder
.build()
149 # Add container to pod spec
150 pod_spec_builder
.add_container(container
)
151 return pod_spec_builder
.build()
154 if __name__
== "__main__":