Rename a host in Ambari
Ambari
might be tricky for some real life operation, like moving a component from a
dead node to another (for instance, the App Timeline Server can't be moved to
another host if the current host is dead). We end-up in particular corner cases
where it's easier to rename a node in db than failing to move the component.
But updating the hostname is not as straight forward as update hosts set
host_name = 'new-hostname' where host_name = 'old-hostname' because the primary key in different tables is the
hostname.
Updating all hostname in all the required tables in the same transaction does
not work either, because the constraint will fail while doing the update. We
should defer constraint checks to ensure the transaction is run successfully.
Mysql
If you choose Mysql as the backend DB, lucky you, it's fairly trivial:
SET FOREIGN_KEY_CHECKS=0;
BEGIN;
UPDATE ambari.clusterhostmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.configgrouphostmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.host_role_command set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostcomponentdesiredstate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostcomponentstate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostconfigmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hoststate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hosts set host_name = '${new-name}' WHERE host_name = '${old-name}';
COMMIT;
SET FOREIGN_KEY_CHECKS=1;
Postgresql
If you have Postgres as the backend DB, well, there's a bit more work to do:
- Delete the constraints about hosts.host_name primary key (yes, really)
- Update the hostname
- Re-created the foreign key constraints
Automatically find
the constraint
Connect to postgres with the admin user
sudo su - postgres
psql -d ambari
Run a query which will generate the ALTER command to drop all the
constraints on hosts.host_name
SELECT 'ALTER TABLE '||nspname||'.'||relname||' DROP CONSTRAINT '||conname||';'
FROM pg_constraint
INNER JOIN pg_class ON conrelid=pg_class.oid
INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
where conname in ('hstcmponentdesiredstatehstname', 'hostcomponentstate_host_name', 'fk_hoststate_host_name',
'fk_hostconfmapping_host_name', 'fk_host_role_command_host_name', 'fk_cghm_hname', 'clusterhostmapping_cluster_id')
ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname;
Run a query which will generate the ALTER command to create all the constraints
on hosts.host_name
SELECT 'ALTER TABLE '||nspname||'.'||relname||' ADD CONSTRAINT '||conname||' '|| pg_get_constraintdef(pg_constraint.oid)||';'
FROM pg_constraint
INNER JOIN pg_class ON conrelid=pg_class.oid
INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
where conname in ('hstcmponentdesiredstatehstname', 'hostcomponentstate_host_name', 'fk_hoststate_host_name', 'fk_hostconfmapping_host_name',
'fk_host_role_command_host_name', 'fk_cghm_hname', 'clusterhostmapping_cluster_id')
ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END DESC,contype DESC,nspname DESC,relname DESC,conname DESC;
Save the ALTER commands in you favorite text editor for later, or use the ones provided below.
Delete the constraints
ALTER TABLE ambari.clusterhostmapping DROP CONSTRAINT clusterhostmapping_cluster_id;
ALTER TABLE ambari.configgrouphostmapping DROP CONSTRAINT fk_cghm_hname;
ALTER TABLE ambari.host_role_command DROP CONSTRAINT fk_host_role_command_host_name;
ALTER TABLE ambari.hostcomponentdesiredstate DROP CONSTRAINT hstcmponentdesiredstatehstname;
ALTER TABLE ambari.hostcomponentstate DROP CONSTRAINT hostcomponentstate_host_name;
ALTER TABLE ambari.hostconfigmapping DROP CONSTRAINT fk_hostconfmapping_host_name;
ALTER TABLE ambari.hoststate DROP CONSTRAINT fk_hoststate_host_name;
Update the hostname
Replace ${old-name} and ${new-name} with the appropriate values.
BEGIN;
UPDATE ambari.clusterhostmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.configgrouphostmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.host_role_command set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostcomponentdesiredstate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostcomponentstate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hostconfigmapping set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hoststate set host_name = '${new-name}' WHERE host_name = '${old-name}';
UPDATE ambari.hosts set host_name = '${new-name}' WHERE host_name = '${old-name}';
COMMIT;
Recreate
the constaints
ALTER TABLE ambari.hoststate ADD CONSTRAINT fk_hoststate_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.hostconfigmapping ADD CONSTRAINT fk_hostconfmapping_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.hostcomponentstate ADD CONSTRAINT hostcomponentstate_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.hostcomponentdesiredstate ADD CONSTRAINT hstcmponentdesiredstatehstname FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.host_role_command ADD CONSTRAINT fk_host_role_command_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.configgrouphostmapping ADD CONSTRAINT fk_cghm_hname FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
ALTER TABLE ambari.clusterhostmapping ADD CONSTRAINT clusterhostmapping_cluster_id FOREIGN KEY (host_name) REFERENCES ambari.hosts(host_name);
Done.
Restart ambari-server
Once you updated the hostname, you need to restart ambari-server.
Actually, you might want to shut it down before running the queries to ensure consistent state of the db.