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
26 from typing
import NoReturn
28 from ops
.main
import main
30 from opslib
.osm
.charm
import CharmedOsmBase
, RelationsMissing
32 from opslib
.osm
.pod
import (
38 from opslib
.osm
.validator
import (
43 from opslib
.osm
.interfaces
.kafka
import KafkaClient
44 from opslib
.osm
.interfaces
.mysql
import MysqlClient
45 from opslib
.osm
.interfaces
.mongo
import MongoClient
48 logger
= logging
.getLogger(__name__
)
53 class ConfigModel(ModelValidator
):
55 database_commonkey
: str
61 @validator("log_level")
62 def validate_log_level(cls
, v
):
63 if v
not in {"INFO", "DEBUG"}:
64 raise ValueError("value must be INFO or DEBUG")
68 class RoCharm(CharmedOsmBase
):
69 """GrafanaCharm Charm."""
71 def __init__(self
, *args
) -> NoReturn
:
72 """Prometheus Charm constructor."""
73 super().__init
__(*args
, oci_image
="image")
75 self
.kafka_client
= KafkaClient(self
, "kafka")
76 self
.framework
.observe(self
.on
["kafka"].relation_changed
, self
.configure_pod
)
77 self
.framework
.observe(self
.on
["kafka"].relation_broken
, self
.configure_pod
)
79 self
.mysql_client
= MysqlClient(self
, "mysql")
80 self
.framework
.observe(self
.on
["mysql"].relation_changed
, self
.configure_pod
)
81 self
.framework
.observe(self
.on
["mysql"].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
.framework
.observe(self
.on
["ro"].relation_joined
, self
._publish
_ro
_info
)
89 def _publish_ro_info(self
, event
):
90 """Publishes RO information.
93 event (EventBase): RO relation event.
95 if self
.unit
.is_leader():
97 "host": self
.model
.app
.name
,
100 for k
, v
in rel_data
.items():
101 event
.relation
.data
[self
.app
][k
] = v
103 def _check_missing_dependencies(self
, config
: ConfigModel
):
104 missing_relations
= []
106 if config
.enable_ng_ro
:
107 if self
.kafka_client
.is_missing_data_in_unit():
108 missing_relations
.append("kafka")
109 if self
.mongodb_client
.is_missing_data_in_unit():
110 missing_relations
.append("mongodb")
112 if self
.mysql_client
.is_missing_data_in_unit():
113 missing_relations
.append("mysql")
114 if missing_relations
:
115 raise RelationsMissing(missing_relations
)
117 def build_pod_spec(self
, image_info
):
119 config
= ConfigModel(**dict(self
.config
))
121 self
._check
_missing
_dependencies
(config
)
122 # Create Builder for the PodSpec
123 pod_spec_builder
= PodSpecV3Builder()
125 container_builder
= ContainerV3Builder(self
.app
.name
, image_info
)
126 container_builder
.add_port(name
=self
.app
.name
, port
=PORT
)
127 container_builder
.add_http_readiness_probe(
128 "/ro/" if config
.enable_ng_ro
else "/openmano/tenants",
130 initial_delay_seconds
=10,
135 container_builder
.add_http_liveness_probe(
136 "/ro/" if config
.enable_ng_ro
else "/openmano/tenants",
138 initial_delay_seconds
=600,
143 container_builder
.add_envs(
145 "OSMRO_LOG_LEVEL": config
.log_level
,
148 if config
.enable_ng_ro
:
149 container_builder
.add_envs(
151 "OSMRO_MESSAGE_DRIVER": "kafka",
152 "OSMRO_MESSAGE_HOST": self
.kafka_client
.host
,
153 "OSMRO_MESSAGE_PORT": self
.kafka_client
.port
,
154 # MongoDB configuration
155 "OSMRO_DATABASE_DRIVER": "mongo",
156 "OSMRO_DATABASE_URI": self
.mongodb_client
.connection_string
,
157 "OSMRO_DATABASE_COMMONKEY": config
.database_commonkey
,
162 container_builder
.add_envs(
164 "RO_DB_HOST": self
.mysql_client
.host
,
165 "RO_DB_OVIM_HOST": self
.mysql_client
.host
,
166 "RO_DB_PORT": self
.mysql_client
.port
,
167 "RO_DB_OVIM_PORT": self
.mysql_client
.port
,
168 "RO_DB_USER": self
.mysql_client
.user
,
169 "RO_DB_OVIM_USER": self
.mysql_client
.user
,
170 "RO_DB_PASSWORD": self
.mysql_client
.password
,
171 "RO_DB_OVIM_PASSWORD": self
.mysql_client
.password
,
172 "RO_DB_ROOT_PASSWORD": self
.mysql_client
.root_password
,
173 "RO_DB_OVIM_ROOT_PASSWORD": self
.mysql_client
.root_password
,
174 "RO_DB_NAME": config
.ro_database
,
175 "RO_DB_OVIM_NAME": config
.vim_database
,
176 "OPENMANO_TENANT": config
.openmano_tenant
,
179 container
= container_builder
.build()
180 # Add container to pod spec
181 pod_spec_builder
.add_container(container
)
182 return pod_spec_builder
.build()
185 if __name__
== "__main__":