# limitations under the License.
import asyncio
+from typing import Union
import os
import uuid
import yaml
import binascii
from n2vc.config import EnvironConfig
+from n2vc.definitions import RelationEndpoint
from n2vc.exceptions import K8sException
from n2vc.k8s_conn import K8sConnector
from n2vc.kubectl import Kubectl
db_uri = EnvironConfig(prefixes=["OSMLCM_", "OSMMON_"]).get("database_uri")
self._store = MotorStore(db_uri)
self.loading_libjuju = asyncio.Lock(loop=self.loop)
+ self.uninstall_locks = {}
self.log.debug("K8S Juju connector initialized")
# TODO: Remove these commented lines:
cleanup_data.append(
{
"delete": kubectl.delete_cluster_role,
- "args": (metadata_name),
+ "args": (metadata_name,),
}
)
cleanup_data.append(
{
"delete": kubectl.delete_service_account,
- "args": (metadata_name),
+ "args": (metadata_name,),
}
)
cleanup_data.append(
{
"delete": kubectl.delete_service_account,
- "args": (metadata_name),
+ "args": (metadata_name,),
}
)
token, client_cert_data = await kubectl.get_secret_data(
raise K8sException("bundle must be set")
if bundle.startswith("cs:"):
+ # For Juju Bundles provided by the Charm Store
+ pass
+ elif bundle.startswith("ch:"):
+ # For Juju Bundles provided by the Charm Hub (this only works for juju version >= 2.9)
pass
elif bundle.startswith("http"):
# Download the file
"""
self.log.debug("[uninstall] Destroying model")
- libjuju = await self._get_libjuju(kwargs.get("vca_id"))
- await libjuju.destroy_model(kdu_instance, total_timeout=3600)
+ will_not_delete = False
+ if kdu_instance not in self.uninstall_locks:
+ self.uninstall_locks[kdu_instance] = asyncio.Lock(loop=self.loop)
+ delete_lock = self.uninstall_locks[kdu_instance]
+
+ while delete_lock.locked():
+ will_not_delete = True
+ await asyncio.sleep(0.1)
- # self.log.debug("[uninstall] Model destroyed and disconnecting")
- # await controller.disconnect()
+ if will_not_delete:
+ self.log.info("Model {} deleted by another worker.".format(kdu_instance))
+ return True
+
+ try:
+ async with delete_lock:
+ libjuju = await self._get_libjuju(kwargs.get("vca_id"))
+ await libjuju.destroy_model(kdu_instance, total_timeout=3600)
+ finally:
+ self.uninstall_locks.pop(kdu_instance)
+
+ self.log.debug(f"[uninstall] Model {kdu_instance} destroyed")
return True
- # TODO: Remove these commented lines
- # if not self.authenticated:
- # self.log.debug("[uninstall] Connecting to controller")
- # await self.login(cluster_uuid)
async def exec_primitive(
self,
complete_status: bool = False,
yaml_format: bool = False,
**kwargs,
- ) -> dict:
+ ) -> Union[str, dict]:
"""Get the status of the KDU
Get the current status of the KDU instance.
return status
+ async def add_relation(
+ self,
+ provider: RelationEndpoint,
+ requirer: RelationEndpoint,
+ ):
+ """
+ Add relation between two charmed endpoints
+
+ :param: provider: Provider relation endpoint
+ :param: requirer: Requirer relation endpoint
+ """
+ self.log.debug(f"adding new relation between {provider} and {requirer}")
+ cross_model_relation = (
+ provider.model_name != requirer.model_name
+ or requirer.vca_id != requirer.vca_id
+ )
+ try:
+ if cross_model_relation:
+ # Cross-model relation
+ provider_libjuju = await self._get_libjuju(provider.vca_id)
+ requirer_libjuju = await self._get_libjuju(requirer.vca_id)
+ offer = await provider_libjuju.offer(provider)
+ if offer:
+ saas_name = await requirer_libjuju.consume(
+ requirer.model_name, offer, provider_libjuju
+ )
+ await requirer_libjuju.add_relation(
+ requirer.model_name,
+ requirer.endpoint,
+ saas_name,
+ )
+ else:
+ # Standard relation
+ vca_id = provider.vca_id
+ model = provider.model_name
+ libjuju = await self._get_libjuju(vca_id)
+ # add juju relations between two applications
+ await libjuju.add_relation(
+ model_name=model,
+ endpoint_1=provider.endpoint,
+ endpoint_2=requirer.endpoint,
+ )
+ except Exception as e:
+ message = f"Error adding relation between {provider} and {requirer}: {e}"
+ self.log.error(message)
+ raise Exception(message=message)
+
async def update_vca_status(self, vcastatus: dict, kdu_instance: str, **kwargs):
"""
Add all configs, actions, executed actions of all applications in a model to vcastatus dict