def deploy(self, verbose, workdir): thread_utils.print_thread(" Deploying {}".format(self.tosca_id)) self.set_state(NodeState.CREATING) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.CREATE, verbose, workdir) self.set_state(NodeState.CREATED) self.set_state(NodeState.CONFIGURING) self._configure_requirements(ConfigureInterfaceOperation.PRE_CONFIGURE_SOURCE, ConfigureInterfaceOperation.PRE_CONFIGURE_TARGET, verbose, workdir) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.CONFIGURE, verbose, workdir) self._configure_requirements(ConfigureInterfaceOperation.POST_CONFIGURE_SOURCE, ConfigureInterfaceOperation.POST_CONFIGURE_TARGET, verbose, workdir) self.set_state(NodeState.CONFIGURED) self.set_state(NodeState.STARTING) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.START, verbose, workdir) self.set_state(NodeState.STARTED) # TODO(@tadeboro): Execute various add hooks thread_utils.print_thread(" Deployment of {} complete".format(self.tosca_id))
def run(self, host: OperationHost, instance, verbose, workdir, validate): thread_utils.print_thread( f" Executing {self.name} on {instance.tosca_id}") # TODO(@tadeboro): Respect the timeout option. # TODO(@tadeboro): Add host validation. # TODO(@tadeboro): Properly handle SELF - not even sure what this # proper way would be at this time. host = self.host or host if host in (OperationHost.SELF, OperationHost.HOST): actual_host = instance.get_host() elif host == OperationHost.SOURCE: actual_host = instance.source.get_host() elif host == OperationHost.TARGET: actual_host = instance.target.get_host() else: # ORCHESTRATOR actual_host = "localhost" operation_inputs = { k: v.eval(instance, k) for k, v in self.inputs.items() } # TODO: Currently when primary is None we skip running the operation. Fix this if needed. if not self.primary: return True, {}, {} # TODO(@tadeboro): Generalize executors. success, ansible_outputs = ansible.run( actual_host, str(self.primary), tuple(str(i) for i in self.dependencies), tuple(str(i) for i in self.artifacts), operation_inputs, verbose, workdir, validate) if not success: return False, {}, {} outputs = [] unresolved_outputs = [] for output, attribute_mapping in self.outputs.items(): if output in ansible_outputs: outputs.append((attribute_mapping, ansible_outputs[output])) ansible_outputs.pop(output) else: unresolved_outputs.append(output) if len(unresolved_outputs) > 0: raise DataError( f"Operation did not return the following outputs: {', '.join(unresolved_outputs)}" ) return success, outputs, ansible_outputs
def notify(self, verbose: bool, workdir: str, trigger_name_or_event: Optional[str], notification_file_contents: Optional[str]): thread_utils.print_thread(f" Notifying {self.tosca_id}") for policy in self.template.policies: for trigger_name, trigger in policy.triggers.items(): # break here if trigger is not targeting this node if trigger.target_filter and trigger.target_filter[ 0] != self.template.name: break invoke_trigger = True if trigger_name_or_event is not None and trigger_name_or_event not in ( trigger_name, trigger.event.data): invoke_trigger = False # invoke the chosen trigger only if it contains any actions if invoke_trigger and trigger.action: thread_utils.print_thread( f" Calling trigger {trigger_name} with event {trigger.event}" ) self.invoke_trigger(verbose, workdir, trigger, notification_file_contents) thread_utils.print_thread( f" Calling trigger actions with event {trigger.event} complete" ) self.notified = True thread_utils.print_thread( f" Notification on {self.tosca_id} complete")
def run(self, host, instance, verbose, workdir): thread_utils.print_thread( " Executing {} on {}".format(self.name, instance.tosca_id) ) # TODO(@tadeboro): Respect the timeout option. # TODO(@tadeboro): Add host validation. # TODO(@tadeboro): Properly handle SELF - not even sure what this # proper way would be at this time. host = self.host or host if host in ("SELF", "HOST"): actual_host = instance.get_host() elif host == "SOURCE": actual_host = instance.source.get_host() elif host == "TARGET": actual_host = instance.target.get_host() else: # ORCHESTRATOR actual_host = "localhost" operation_inputs = { k: v.eval(instance, k) for k, v in self.inputs.items() } # TODO(@tadeboro): Generalize executors. success, ansible_outputs = ansible.run( actual_host, str(self.primary), tuple(str(i) for i in self.dependencies), tuple(str(i) for i in self.artifacts), operation_inputs, verbose, workdir ) if not success: return False, {}, {} outputs = [] unresolved_outputs = [] for output, attribute_mapping in self.outputs.items(): if output in ansible_outputs: outputs.append((attribute_mapping, ansible_outputs[output])) ansible_outputs.pop(output) else: unresolved_outputs.append(output) if len(unresolved_outputs) > 0: raise DataError( "Operation did not return the following outputs: {}".format( ", ".join(unresolved_outputs))) return success, outputs, ansible_outputs
def undeploy(self, verbose, workdir): thread_utils.print_thread(" Undeploying {}".format(self.tosca_id)) self.set_state("stopping") self.run_operation("HOST", "Standard", "stop", verbose, workdir) self.set_state("configured") self.set_state("deleting") self.run_operation("HOST", "Standard", "delete", verbose, workdir) self.set_state("initial") # TODO(@tadeboro): Execute various remove hooks self.reset_attributes() self.write() thread_utils.print_thread(" Undeployment of {} complete".format( self.tosca_id))
def undeploy(self, verbose, workdir): thread_utils.print_thread(" Undeploying {}".format(self.tosca_id)) self.set_state(NodeState.STOPPING) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.STOP, verbose, workdir) self.set_state(NodeState.CONFIGURED) self.set_state(NodeState.DELETING) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.DELETE, verbose, workdir) self.set_state(NodeState.INITIAL) # TODO(@tadeboro): Execute various remove hooks self.reset_attributes() self.write() thread_utils.print_thread(" Undeployment of {} complete".format(self.tosca_id))
def deploy(self, verbose, workdir): thread_utils.print_thread(" Deploying {}".format(self.tosca_id)) self.set_state("creating") self.run_operation("HOST", "Standard", "create", verbose, workdir) self.set_state("created") self.set_state("configuring") for requirement in set([r.name for r in self.template.requirements]): for relationship in self.out_edges[requirement].values(): relationship.run_operation( "SOURCE", "Configure", "pre_configure_source", verbose, workdir ) for requirement_dependants in self.in_edges.values(): for relationship in requirement_dependants.values(): relationship.run_operation( "TARGET", "Configure", "pre_configure_target", verbose, workdir ) self.run_operation("HOST", "Standard", "configure", verbose, workdir) for requirement in set([r.name for r in self.template.requirements]): for relationship in self.out_edges[requirement].values(): relationship.run_operation( "SOURCE", "Configure", "post_configure_source", verbose, workdir ) for requirement_dependants in self.in_edges.values(): for relationship in requirement_dependants.values(): relationship.run_operation( "TARGET", "Configure", "post_configure_target", verbose, workdir ) self.set_state("configured") self.set_state("starting") self.run_operation("HOST", "Standard", "start", verbose, workdir) self.set_state("started") # TODO(@tadeboro): Execute various add hooks thread_utils.print_thread( " Deployment of {} complete".format(self.tosca_id) )
def validate(self, verbose, workdir): thread_utils.print_thread(f" Validating {self.tosca_id}") # validate node's deployment self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.CREATE, verbose, workdir, True) self._configure_requirements( ConfigureInterfaceOperation.PRE_CONFIGURE_SOURCE, ConfigureInterfaceOperation.PRE_CONFIGURE_TARGET, verbose, workdir, True) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.CONFIGURE, verbose, workdir, True) self._configure_requirements( ConfigureInterfaceOperation.POST_CONFIGURE_SOURCE, ConfigureInterfaceOperation.POST_CONFIGURE_TARGET, verbose, workdir, True) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.START, verbose, workdir, True) # validate node's undeployment self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.STOP, verbose, workdir, True) self.run_operation(OperationHost.HOST, StandardInterfaceOperation.shorthand_name(), StandardInterfaceOperation.DELETE, verbose, workdir, True) self.reset_attributes() self.write() self.validated = True thread_utils.print_thread(f" Validation of {self.tosca_id} complete")
def run(host, primary, dependencies, artifacts, variables, verbose, workdir): # pylint: disable=too-many-locals with tempfile.TemporaryDirectory() as dir_path: playbook = os.path.join(dir_path, os.path.basename(primary)) utils.copy(os.path.join(workdir, primary), playbook) for d in dependencies: utils.copy(os.path.join(workdir, d), os.path.join(dir_path, os.path.basename(d))) for a in artifacts: utils.copy(os.path.join(workdir, a), os.path.join(dir_path, os.path.basename(a))) inventory = utils.write(dir_path, _get_inventory(host), suffix=".yaml") vars_file = utils.write(dir_path, yaml.safe_dump(variables), suffix=".yaml") with open("{}/ansible.cfg".format(dir_path), "w") as fd: fd.write("[defaults]\n") fd.write("retry_files_enabled = False\n") opera_ssh_host_key_checking = os.environ.get( "OPERA_SSH_HOST_KEY_CHECKING") if opera_ssh_host_key_checking is not None: check = str(opera_ssh_host_key_checking).lower().strip() if check[:1] == "f" or check[:1] == "false": fd.write("host_key_checking = False\n") if verbose: print("***inputs***") print(["{}: {}".format(key, variables[key]) for key in variables]) print("***inputs***") cmd = [ "ansible-playbook", "-i", inventory, "-e", "@" + vars_file, playbook ] env = dict( ANSIBLE_SHOW_CUSTOM_STATS="1", ANSIBLE_STDOUT_CALLBACK="json", ) code, out, err = utils.run_in_directory(dir_path, cmd, env) if code != 0 or verbose: thread_utils.print_thread("------------") with open(out) as fd: for line in fd: print(line.rstrip()) thread_utils.print_thread("------------") with open(err) as fd: for line in fd: print(line.rstrip()) thread_utils.print_thread("============") if code != 0: return False, {} with open(out) as fd: outputs = json.load(fd)["global_custom_stats"] return code == 0, outputs