CORE-1779 Reset mnt/state/var folder permissions

Due to launchpad bug # 1374626, UIDs can change between full image
deployments as accounts are burned into the image and depending on
the elements included between images, may have differing owners.

As a result, this commit, while it does not fix the root cause, is
intended to reset the permissions so applications can start after
an upgrade.

Change-Id: I83b7efda5dbf8a7d587d1a638916b8f6f755cb2d
This commit is contained in:
Julia Kreger 2014-09-29 10:23:19 -04:00 committed by Clint Byrum
parent c0c50d0bb9
commit fa3c816396
4 changed files with 230 additions and 0 deletions

View File

@ -0,0 +1,176 @@
#!/usr/bin/env python
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import grp
import optparse
import os
import pwd
import stat
def get_object_ids(file):
stat_information = os.stat(file)
return(stat_information.st_uid, stat_information.st_gid)
def get_username_from_uid(old_uid, old_password_file):
file = open(old_password_file)
passwd_file = file.readlines()
for user_entry in passwd_file:
(
user,
passwd,
uid,
gid,
gecos,
home,
shell
) = user_entry.split(':')
if old_uid == int(uid):
return user
return "ErrUserNotFound"
def get_groupname_from_gid(old_gid, old_group_file):
file = open(old_group_file)
group_file = file.readlines()
for group_entry in group_file:
(
group,
passwd,
gid,
members
) = group_entry.split(':')
if old_gid == int(gid):
return group
return "ErrUserNotFound"
def get_new_uid(username):
return pwd.getpwnam(username).pw_uid
def get_new_gid(groupname):
return grp.getgrnam(groupname).gr_gid
def run_check(object, old_password_file, old_group_file):
(old_uid, old_gid) = get_object_ids(object)
old_username = get_username_from_uid(old_uid, old_password_file)
old_groupname = get_groupname_from_gid(old_uid, old_group_file)
try:
new_uid = get_new_uid(old_username)
new_gid = get_new_gid(old_groupname)
if old_uid != new_uid:
if old_username in object:
return(True, old_username, new_uid, old_groupname, new_gid)
return(False, old_username, new_uid, old_groupname, old_gid)
except:
return(False, old_username, -1, old_groupname, -1)
def recursive_update(directory, new_uid, new_gid):
os.chown(directory, new_uid, new_gid)
for root, dirs, files in os.walk(directory):
for dir in dirs:
os.chown(os.path.join(root, dir), new_uid, new_gid)
for file in files:
os.chown(os.path.join(root, file), new_uid, new_gid)
def main():
usage = "Usage: %prog -f old_password_file -d directory_to_update"
parser = optparse.OptionParser(usage)
parser.add_option(
"-f",
action="store",
default=False,
dest="old_password_file",
help="Path to previous system password file"
)
parser.add_option(
"-g",
action="store",
default=False,
dest="old_group_file",
help="Path to previous system password file"
)
parser.add_option(
"-d",
action="store",
default=False,
dest="directory",
help="Directory to check and apply permission updates to"
)
(options, args) = parser.parse_args()
if not options.directory:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
if not options.old_password_file:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
if not options.old_group_file:
print("Error: please define a directory to run the program with -d")
parser.print_help()
return -1
for object in os.listdir(options.directory):
if os.path.isdir(os.path.join(options.directory, object)):
(changed, old_user, new_uid, old_groupname, new_gid) = run_check(
os.path.join(options.directory, object),
options.old_password_file,
options.old_group_file
)
if changed:
print("Updating %s/%s for ownership to uid %s for %s" % (
options.directory,
object,
new_uid,
old_user
)
)
try:
recursive_update(
os.path.join(options.directory, object),
new_uid,
new_gid
)
except:
print("Failed to update ownership of %s/%s " % (
options.directory,
object
)
)
else:
print("ignoring %s/%s" % (
options.directory,
object
)
)
else:
print("Ignoring %s/%s as it is not a directory" % (
options.directory,
object
)
)
main()

View File

@ -0,0 +1,23 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- name: "Ensure /mnt/state/etc exists"
sudo: yes
file: path=/mnt/state/etc owner=root group=root mode=0755 state=directory
- name: "Saving a copy of /etc/passwd to /mnt/state/etc/passwd.backup"
sudo: yes
command: cp -a /etc/passwd /mnt/state/etc/passwd.backup
- name: "Saving a copy of /etc/group to /mnt/state/etc/passwd.backup"
sudo: yes
command: cp -a /etc/group /mnt/state/etc/group.backup

View File

@ -0,0 +1,21 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- name: "Correcting Permissions for /mnt/state/var/log"
sudo: yes
script: files/correct_mnt_state_permissions.py -f /mnt/state/etc/passwd.backup -g /mnt/state/etc/group.backup -d /mnt/state/var/log
- name: "Correcting Permissions for /mnt/state/var/lib"
sudo: yes
script: files/correct_mnt_state_permissions.py -f /mnt/state/etc/passwd.backup -g /mnt/state/etc/group.backup -d /mnt/state/var/lib
- include: step_preserve_password_file.yml

View File

@ -167,6 +167,8 @@
gather_facts: no
max_fail_percentage: 0
tasks:
- include: step_preserve_password_file.yml
when: instance_status == "ACTIVE"
- include: preserve_ssh_host_keys.yml
when: instance_status == "ACTIVE"
- include: cleanup_cinder_volumes.yml
@ -202,6 +204,8 @@
gather_facts: no
max_fail_percentage: 0
tasks:
- include: step_preserve_password_file.yml
when: instance_status == "ACTIVE"
- include: preserve_ssh_host_keys.yml
when: instance_status == "ACTIVE"
- include: cleanup_cinder_volumes.yml
@ -231,6 +235,7 @@
file: path=/mnt/state/disable-os-collect-config state=absent
- name: "Run os-collect-config"
command: os-collect-config --force --one
- include: step_reset_mnt_state_permissions.yml
- name: Bootstrap the MySQL cluster
command: /etc/init.d/mysql bootstrap-pxc
when: single_controller is not defined
@ -248,6 +253,8 @@
gather_facts: no
max_fail_percentage: 0
tasks:
- include: step_preserve_password_file.yml
when: instance_status == "ACTIVE"
- include: preserve_ssh_host_keys.yml
when: instance_status == "ACTIVE"
- include: cleanup_cinder_volumes.yml
@ -271,6 +278,7 @@
- include: mysql_init_fix.yml
- include: stop_mysql.yml
- include: rabbitmq_occ_disable.yml
- include: step_reset_mnt_state_permissions.yml
- include: refresh_config.yml
- name: Stop os-collect-config to avoid collission
service: name=os-collect-config state=stopped
@ -399,6 +407,8 @@
gather_facts: no
max_fail_percentage: 0
tasks:
- include: step_preserve_password_file.yml
when: instance_status == "ACTIVE"
- include: preserve_ssh_host_keys.yml
when: instance_status == "ACTIVE"
- { include: rebuild.yml, instance_id: "{{ instance_id }}", rebuild_image_id: "{{ nova_compute_rebuild_image_id }}", when: instance_status != "REBUILD" }