from juju.action import Action
from juju.machine import Machine
from juju.client import client
+from juju.errors import JujuAPIError
from n2vc.provisioner import SSHProvisioner
self.debug('adding new relation between {} and {}, endpoints: {}, {}'
.format(ee_id_1, ee_id_2, endpoint_1, endpoint_2))
+ # check arguments
+ if not ee_id_1:
+ message = 'EE 1 is mandatory'
+ self.error(message)
+ raise N2VCBadArgumentsException(message=message, bad_args=['ee_id_1'])
+ if not ee_id_2:
+ message = 'EE 2 is mandatory'
+ self.error(message)
+ raise N2VCBadArgumentsException(message=message, bad_args=['ee_id_2'])
+ if not endpoint_1:
+ message = 'endpoint 1 is mandatory'
+ self.error(message)
+ raise N2VCBadArgumentsException(message=message, bad_args=['endpoint_1'])
+ if not endpoint_2:
+ message = 'endpoint 2 is mandatory'
+ self.error(message)
+ raise N2VCBadArgumentsException(message=message, bad_args=['endpoint_2'])
+
if not self._authenticated:
await self._juju_login()
- # get model, application and machines
+ # get the model, the applications and the machines from the ee_id's
model_1, app_1, machine_1 = self._get_ee_id_components(ee_id_1)
model_2, app_2, machine_2 = self._get_ee_id_components(ee_id_2)
# add juju relations between two applications
try:
- self._juju_add_relation()
+ await self._juju_add_relation(
+ model_name=model_1,
+ application_name_1=app_1,
+ application_name_2=app_2,
+ relation_1=endpoint_1,
+ relation_2=endpoint_2
+ )
except Exception as e:
message = 'Error adding relation between {} and {}'.format(ee_id_1, ee_id_2)
self.error(message)
.format(ee_id, application_name, e))
# destroy the machine
- try:
- await self._juju_destroy_machine(
- model_name=model_name,
- machine_id=machine_id,
- total_timeout=total_timeout
- )
- except Exception as e:
- raise N2VCException(message='Error deleting execution environment {} (machine {}) : {}'
- .format(ee_id, machine_id, e))
+ # try:
+ # await self._juju_destroy_machine(
+ # model_name=model_name,
+ # machine_id=machine_id,
+ # total_timeout=total_timeout
+ # )
+ # except Exception as e:
+ # raise N2VCException(message='Error deleting execution environment {} (machine {}) : {}'
+ # .format(ee_id, machine_id, e))
self.info('Execution environment {} deleted'.format(ee_id))
relation_2: str
):
- self.debug('adding relation')
-
# get juju model and observer
model = await self._juju_get_model(model_name=model_name)
r1 = '{}:{}'.format(application_name_1, relation_1)
r2 = '{}:{}'.format(application_name_2, relation_2)
- await model.add_relation(relation1=r1, relation2=r2)
+
+ self.debug('adding relation: {} -> {}'.format(r1, r2))
+ try:
+ await model.add_relation(relation1=r1, relation2=r2)
+ except JujuAPIError as e:
+ # If one of the applications in the relationship doesn't exist, or the relation has already been added,
+ # let the operation fail silently.
+ if 'not found' in e.message:
+ return
+ if 'already exists' in e.message:
+ return
+ # another execption, raise it
+ raise e
async def _juju_destroy_application(
self,
# get juju model and observer
model = await self._juju_get_model(model_name=model_name)
+ observer = self.juju_observers[model_name]
application = model.applications.get(application_name)
if application:
+ observer.unregister_application(application_name)
await application.destroy()
else:
self.debug('Application not found: {}'.format(application_name))
# get juju model and observer
model = await self._juju_get_model(model_name=model_name)
+ observer = self.juju_observers[model_name]
machines = await model.get_machines()
if machine_id in machines:
machine = model.machines[machine_id]
+ observer.unregister_machine(machine_id)
await machine.destroy(force=True)
# max timeout
end = time.time() + total_timeout
model = await self._juju_get_model(model_name=model_name)
uuid = model.info.uuid
+ # destroy machines
+ machines = await model.get_machines()
+ for machine_id in machines:
+ try:
+ await self._juju_destroy_machine(model_name=model_name, machine_id=machine_id)
+ except Exception as e:
+ # ignore exceptions destroying machine
+ pass
+
await self._juju_disconnect_model(model_name=model_name)
self.juju_models[model_name] = None
self.juju_observers[model_name] = None