How to instruct Ansible for remote node command to find a text resource file on remote node - ansible

I am trying to upgrade some Jboss servers for my application running on remote nodes using Ansible. Through Ansible I can invoke a jboss server start script which has to upgrade and start my server on remote node.
Problem is that the script internally takes a configuration property file as an argument which resides on the remote server (there are many such servers and every server has different configuration property file which resides within the remote node server so I cannot keep these files locally on ansible controller machine) on which actually upgrade is running. However Ansible expects that the resource file should be available on ansible controller (locally) and fails to do the upgrade.
Is there any way I can instruct Ansible to find the particular resource or file directly on the remote node rather then finding it locally and then copying every resource on remote node for execution?
Ansible Playbook file contents
---
- name: Upgrade Server
hosts: remote_host
connection: ssh
vars:
server_version: 188
server_name: UpgradeTest
tasks:
- name: Start server
shell: "{{ jboss_home }}/bin/startJBossServer.sh {{ server_name }} >/dev/null 2>&1 &"
- name: Wait for port {{ server_http_port }} to come up
wait_for: host="localhost" port="{{ server_http_port }}" delay=15 timeout=300 state=started
- name: Test server is up and running
action: uri url="http://localhost:{{ server_http_port }}/{{ server_name }}" return_content=yes timeout=90
register: webpage
until: webpage.status == 200
retries: 25
delay: 5
The file startJBossServer.sh contains the following command:
nohup "${JBOSS_HOME}/bin/standalone.sh" -Djboss.server.base.dir=${JBOSS_HOME}/${i_server_name} -b=0.0.0.0 -c=#fm.config.xml# -P=${start_server_properties_file} </dev/null > "/dev/null" 2>&1 &
If you can see we need ${start_server_properties_file} in -P argument which actually is available on remote node server, however Ansible expects the same resource to be available on local machine and hence fails to run the command.

Related

ansible: copy run scp - just goes on and on never ends

I have below task to copy running config to remote server.
- name: Copying confg to remote server
cisco.nxos.nxos_command:
commands:
- command: copy run scp://{{ username }}#{{ remote_server }}{{ remote_location }}/{{ hostname }}_config.txt vrf management
prompt:
- "password:"
answer:
- "{{ password }}"
I did debug using -vvv. This approach just goes on and on never ends.
> <192.168.1.1> ANSIBLE_NETWORK_IMPORT_MODULES: found cisco.nxos.nxos_command at /usr/local/Cellar/ansible/6.5.0/libexec/lib/python3.10/site-packages/ansible_collections/cisco/nxos/plugins/modules/nxos_command.py
> <192.168.1.1> ANSIBLE_NETWORK_IMPORT_MODULES: running cisco.nxos.nxos_command
how to fix it? I was looking at cisco.nxos.nxos_file_copy module but it is to copy file from remote server to nexus device. I need to copy file from nexus device to remote server so I can't use it.
The scp command syntax looks a little wrong to me. Seems to be missing : after {{ remote_server }}
Example: scp username#server:filepath /local/directory/

Ansible wait_for_connection until the hosts are ready for ansible?

I am using ansible to configure some VM's.
Problem I am facing right now is, I can't execute ansible commands right after the VM's are just started, it gives connection time out error. This happens when I execute the ansible right after the VMs are spinned up in GCP.
Commands working fine when I execute ansible playbook after 60 seconds, but I am looking for a way to do this automatically without manually wait 60s and execute, so I can execute right after VM's are spun up and ansible will wait until they are ready. I don't want to add a delay seconds to ansible tasks as well,
I am looking for a dynamic way where ansible tries to execute playbook and when it fails, it won't show any error but wait until the VM's are ready?
I used this, but it still doesn't work (as it fails)
---
- hosts: all
tasks:
- name: Wait for connection
wait_for_connection: # but this will still fails, am I doing this wrong?
- name: Ping all hosts for connectivity check
ping:
Can someone please help me?
I have the same issue on my side.
I've fixed htis with this task wait_for.
The basic way is to waiting ssh connection like this :
- name: Wait 300 seconds for port 22 to become open and contain "OpenSSH"
wait_for:
port: 22
host: '{{ (ansible_ssh_host|default(ansible_host))|default(inventory_hostname) }}'
search_regex: OpenSSH
delay: 10
connection: local
I guess your VM must launch an application/service so you can monitor on the vm in the log file where application is started, like this for example (here for nexus container):
- name: Wait container is start and running
become: yes
become_user: "{{ ansible_nexus_user }}"
wait_for:
path: "{{ ansible_nexus_directory_data }}/log/nexus.log"
search_regex: ".*Started Sonatype Nexus.*"
I believe what you are looking for is to postpone gather_facts until the server is up, as that otherwise will time out as you experienced. Your file could work as follows:
---
- hosts: all
gather_facts: no
tasks:
- name: Wait for connection (600s default)
ansible.builtin.wait_for_connection:
- name: Gather facts manually
ansible.builtin.wait_for_connection
I have these under pre_tasks instead of tasks, but it should probably work if they are first in your file.

Cant start adminctl because of ## placeholders in admin.conf from Connections 6.5 IHS

I made a Connections 6.5 headless installation which itself works, but couldn't start adminctl in the
# cd /opt/IBM/HTTPServer/bin/
# ./adminctl start
Syntax error on line 7 of /opt/IBM/HTTPServer/conf/admin.conf:
Port must be specified
Line 7 seems like an variable, that doesn't got parsed properly when configuring the IHS
# grep Listen ../conf/admin.conf
Listen ##AdminPort##
There are also other such ## variables in the config file:
# grep ## ../conf/admin.conf
Listen ##AdminPort##
User ##SetupadmUser##
Group ##SetupadmGroup##
ServerName cnx65.internal:##AdminPort##
Why are those values not correctly replaced? For example to Listen 8008 (default IHS admin port).
How I configure the IHS
The machine got provisioned using ansible, where the following shell command runs for IHS plugin configuration:
./wctcmd.sh -tool pct -createDefinition -defLocPathname /opt/IBM/WebSphere/Plugins -response /tmp/plugin-response-file.txt -defLocName webserver1
Response file /tmp/plugin-response-file.txt:
configType=remote
enableAdminServerSupport=true
enableUserAndPass=true
enableWinService=false
ihsAdminCreateUserAndGroup=true
ihsAdminPassword=adminihs
ihsAdminPort=8008
ihsAdminUnixUserGroup=ihsadmin
ihsAdminUnixUserID=ihsadmin
mapWebServerToApplications=true
wasMachineHostname=cnx65.internal
webServerConfigFile1=/opt/IBM/HTTPServer/conf/httpd.conf
webServerDefinition=webserver1
webServerHostName=cnx65.internal
webServerOS=Linux
webServerPortNumber=80
webServerSelected=IHS
As you can see, all required variables for substitution were present. So the tool should be able to replace ##AdminPort## by the value 8008.
wctcmd.sh just creates the WAS definition for the IHS, but doesn't prepare the admin server. We need to do this manually with postinst and setupadm as documented here. This seems not just required for zip installations. My installation was done using Installation Manager and the admin server doesn't work without those steps.
I automated it in Ansible like this:
- name: Check if admin config is properly parsed
become: yes
shell: grep ##AdminPort## {{ http_server.target }}/conf/admin.conf
register: admin_conf_check
# File not found raise rc = 2, rc = 0 found, rc = 1 not found but file exists
failed_when: admin_conf_check.rc != 0 and admin_conf_check.rc != 1
changed_when: False
- set_fact:
admin_conf_is_configured: "{{ admin_conf_check.rc == 1 }}"
- name: Parse IHS admin config
become: yes
# plugin_config_file is defined in http-plugin.yml
shell: |
./bin/postinst -i $PWD -t setupadm -v ADMINPORT={{ http_server.admin_port }} -v SETUPADMUSER=nobody -v SETUPADMGROUP=nobody
./bin/setupadm -usr nobody -grp nobody -cfg conf/httpd.conf -plg {{ plugin_config_file }} -adm conf/admin.conf
args:
chdir: "{{ http_server.target }}"
environment:
LANG: "{{ system_language }}"
register: ihs_setup
# setupadm returns 90 if it was successfull: "Script Completed RC(90)"
failed_when: ihs_setup.rc != 90
when: not admin_conf_is_configured
- name: Create htpasswd for admin config
become: yes
shell: ./bin/htpasswd -c conf/admin.passwd adminihs
args:
chdir: "{{ http_server.target }}"
creates: "{{ http_server.target }}/conf/admin.passwd"
environment:
LANG: "{{ system_language }}"
http_server.target is the IHS base path, e.g. /opt/IBM/HTTPServer
http_server.admin_port is the IBM default value 8008
plugin_config_file is set to /opt/IBM/WebSphere/Plugins/config/{{ http_server.name }}/plugin-cfg.xml where http_server.name matches the definition name in WAS (webserver1 in my example)
system_language is set to en_US.utf8 to make sure that we get english error message for output validation (when required), independent of the configured OS language
After running those configuration tools, we can see that all placeholders were replaced by their corresponding values:
# grep -i listen ../conf/admin.conf
Listen 8008
Running the admin server by executing ./adminctl start in the bin directory now works as expected.
I heard from folks in the lab at IBM that webServerSelected=IHS is not being regognized and it must be webServerSelected=ihs (lowercase)
https://www.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/tins_pctcl_using.html
webServerSelected
Specifies the web server to be configured
Specify only one web server to configure.
apache22
Apache Web Server Version 2.2
64-bit configuration not supported on Windows
apache24
Apache Web Server Version 2.4
64-bit configuration not supported on Windows
ihs
IBM® HTTP Server
64-bit configuration not supported on Windows
...

Ansible AWS EC2 Detecting Server is Running Fails

Background:
Just trying to learn how to use Ansible and have been experimenting with the AWS Ec2 module to build and deploy a Ubuntu instance on AWS-EC2. So have built a simple Playbook to create and startup an instance and executed via ansible-playbook -vvvv ic.yml
The playbook is:
---
- name: Create a ubuntu instance on AWS
hosts: localhost
connection: local
gather_facts: False
vars:
# AWS keys for access to the API
ec2_access_key: 'secret-key'
ec2_secret_key: 'secret-key'
region: ap-southeast-2
tasks:
- name: Create a Key-Pair necessary for connection to the remote EC2 host
ec2_key:
name=ic-key region="{{region}}"
register: keypair
- name: Write the Key-Pair to a file for re-use
copy:
dest: files/ic-key.pem
content: "{{ keypair.key.private_key }}"
mode: 0600
when: keypair.changed
- name: start the instance
ec2:
ec2_access_key: "{{ec2_access_key}}"
ec2_secret_key: "{{ec2_secret_key}}"
region: ap-southeast-2
instance_type: t2.micro
image: ami-69631053
key_name: ic-key # key we just created
instance_tags: {Name: icomplain-prod, type: web, env: production} #key-values pairs for naming etc
wait: yes
register: ec2
- name: Wait for instance to start up and be running
wait_for: host = {{item.public_dns_name}} port 22 delay=60 timeout=320 state=started
with_items: ec2.instances
Problem:
The issue is that when attempting to wait for the instance to fire up, using the wait_for test, as described in Examples for EC-2 module it fails with the following error message:
msg: this module requires key=value arguments (['host', '=', 'ec2-52-64-134-61.ap-southeast-2.compute.amazonaws.com', 'port', '22', 'delay=60', 'timeout=320', 'state=started'])
FATAL: all hosts have already failed -- aborting
Output:
Although the error message appears on the command line when I check in the AWS-Console the Key-Pair and EC2 instance are created and running.
Query:
Wondering
There is some other parameter which I need ?
What is the 'key=value' msg which is the error output being caused by?
Any recommendations on other ways to debug the script to determine the cause of the failure ?
Does it require registration of the host somewhere in the Ansible world ?
Additional NOTES:
Testing the playbook I've observed that the key-pair gets created, the server startup is initiated at AWS as seen from the AWS web console. What appears to be the issue is that the time period of the server to spin up is too long and the script timeouts or fails. Frustratingly, is that the error message is not all that helpful and also wondering if there is any other methods of debugging an ansible script ?
this isn't a problem of "detecting the server is running". As the error message says, it's a problem with syntax.
# bad
wait_for: host = {{item.public_dns_name}} port 22 delay=60 timeout=320 state=started
# good
wait_for: host={{item.public_dns_name}} port=22 delay=60 timeout=320 state=started
Additionally, you'll want to run this from the central machine, not the remote (new) server.
local_action: wait_for host={{item.public_dns_name}} port=22 delay=60 timeout=320 state=started
Focusing on the wait_for test as you indicate that the rest is working.
Based on the jobs I have running I would think the issue is with the host name, not with the rest of the code. I use an Ansible server in a protected VPC that has network access to the VPC where the servers start up in, and my wait_for code looks like this (variable name updated to match yours):
- name: wait for instances to listen on port 22
wait_for:
delay: 10
state: started
host: "{{ item.private_ip }}"
port: 22
timeout: 300
with_items: ec2.instances
Trying to use DNS instead of an IP address has always proven to be unreliable for me - if I'm registering DNS as part of a job, it can sometimes take a minute to be resolvable (sometimes instant, sometimes not). Using the IP addresses works every time of course - as long as the networking is set up correctly.
If your Ansible server is in a different region or has to use the external IP to access the new servers, you will of course need to have the relevant security groups and add the new server(s) to those before you can use wait_for.

Ansible execute command locally and then on remote server

I am trying to start a server using ansible shell module with ipmitools and then do configuration change on that server once its up.
Server with ansible installed also has ipmitools.
On server with ansible i need to execute ipmitools to start target server and then execute playbooks on it.
Is there a way to execute local ipmi commands on server running ansible to start target server through ansible and then execute all playbooks over ssh on target server.
You can run any command locally by providing the delegate_to parameter.
- shell: ipmitools ...
delegate_to: localhost
If ansible complains about connecting to localhost via ssh, you need to add an entry in your inventory like this:
localhost ansible_connection=local
or in host_vars/localhost:
ansible_connection: local
See behavioral parameters.
Next, you're going to need to wait until the server is booted and accessible though ssh. Here is an article from Ansible covering this topic and this is the task they have listed:
- name: Wait for Server to Restart
local_action:
wait_for
host={{ inventory_hostname }}
port=22
delay=15
timeout=300
sudo: false
If that doesn't work (since it is an older article and I think I previously had issues with this solution) you can look into the answers of this SO question.

Resources