Compare commits
No commits in common. "c9416f8604c111f696fb42bb14a46ba209e7d0d3" and "8a1d7e0d4679bef93c0556a55c86711ffd433c9f" have entirely different histories.
c9416f8604
...
8a1d7e0d46
|
@ -3,6 +3,8 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
#import fs
|
||||||
|
#from fs import tempfs, path
|
||||||
import fs.tempfs
|
import fs.tempfs
|
||||||
import fs.path
|
import fs.path
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
@ -23,7 +25,6 @@ class ConfigDrive:
|
||||||
self._interfaces = []
|
self._interfaces = []
|
||||||
self._pubkeys = []
|
self._pubkeys = []
|
||||||
self._verbose = verbose
|
self._verbose = verbose
|
||||||
self._clean_metadata = False
|
|
||||||
|
|
||||||
self._added_resolv_module_call = False
|
self._added_resolv_module_call = False
|
||||||
|
|
||||||
|
@ -91,9 +92,6 @@ class ConfigDrive:
|
||||||
self.add_command("cloud-init single --name cc_resolv_conf", True)
|
self.add_command("cloud-init single --name cc_resolv_conf", True)
|
||||||
self._added_resolv_module_call = True
|
self._added_resolv_module_call = True
|
||||||
|
|
||||||
def set_clean_metadata(self, do_clean_metadata):
|
|
||||||
self._clean_metadata = do_clean_metadata
|
|
||||||
|
|
||||||
def add_user(self, name, keys=None, gecos=None, sudo=False, password=None):
|
def add_user(self, name, keys=None, gecos=None, sudo=False, password=None):
|
||||||
if "users" not in self._user_data:
|
if "users" not in self._user_data:
|
||||||
self._user_data["users"] = []
|
self._user_data["users"] = []
|
||||||
|
@ -129,6 +127,7 @@ class ConfigDrive:
|
||||||
if dir_path and not self._tmpfs.exists(dir_path):
|
if dir_path and not self._tmpfs.exists(dir_path):
|
||||||
self._tmpfs.makedirs(dir_path)
|
self._tmpfs.makedirs(dir_path)
|
||||||
|
|
||||||
|
|
||||||
self._tmpfs.settext(path, content)
|
self._tmpfs.settext(path, content)
|
||||||
if self._verbose:
|
if self._verbose:
|
||||||
print(" >>", path)
|
print(" >>", path)
|
||||||
|
@ -148,10 +147,10 @@ class ConfigDrive:
|
||||||
"files": [],
|
"files": [],
|
||||||
"hostname": self._hostname,
|
"hostname": self._hostname,
|
||||||
"name": self._hostname.split(".")[0],
|
"name": self._hostname.split(".")[0],
|
||||||
# "meta": {
|
#"meta": {
|
||||||
# "role": "webservers",
|
# "role": "webservers",
|
||||||
# "essential": False,
|
# "essential": False,
|
||||||
# }
|
#}
|
||||||
"uuid": str(uuid.uuid4()),
|
"uuid": str(uuid.uuid4()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,15 +165,11 @@ class ConfigDrive:
|
||||||
meta_data["files"].append({"content_path": "/content/0000", "path": "/etc/network/interfaces"})
|
meta_data["files"].append({"content_path": "/content/0000", "path": "/etc/network/interfaces"})
|
||||||
self.add_text("/openstack/content/0000", "\n".join(self._interfaces))
|
self.add_text("/openstack/content/0000", "\n".join(self._interfaces))
|
||||||
|
|
||||||
meta_data["files"].append({"content_path": "/content/0001",
|
meta_data["files"].append({"content_path": "/content/0001", "path": "/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg"})
|
||||||
"path": "/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg"})
|
|
||||||
self.add_text("/openstack/content/0001", "network: {config: disabled}")
|
self.add_text("/openstack/content/0001", "network: {config: disabled}")
|
||||||
|
|
||||||
# do not look for datasource on every boot
|
#meta_data["files"].append({"content_path": "/content/0002", "path": "/etc/cloud/cloud.cfg.d/10-resolv-conf.cfg"})
|
||||||
if self._clean_metadata:
|
#self.add_text("/openstack/content/0002", "cloud_init_modules:\n - resolv-conf\n")
|
||||||
meta_data["files"].append({"content_path": "/content/0002",
|
|
||||||
"path": "/etc/cloud/cloud.cfg.d/99-manual-cache-clean.cfg"})
|
|
||||||
self.add_text("/openstack/content/0002", "manual_cache_clean: True")
|
|
||||||
|
|
||||||
if self._pubkeys:
|
if self._pubkeys:
|
||||||
meta_data["public_keys"] = {}
|
meta_data["public_keys"] = {}
|
||||||
|
@ -201,26 +196,18 @@ class ConfigDrive:
|
||||||
if "chpasswd" not in self._user_data:
|
if "chpasswd" not in self._user_data:
|
||||||
self._user_data["chpasswd"] = {}
|
self._user_data["chpasswd"] = {}
|
||||||
self._user_data["chpasswd"]["list"] = ""
|
self._user_data["chpasswd"]["list"] = ""
|
||||||
# self._user_data["chpasswd"]["list"] = []
|
#self._user_data["chpasswd"]["list"] = []
|
||||||
|
|
||||||
# self._user_data["chpasswd"]["list"].append("%s:%s" % (user, password))
|
#self._user_data["chpasswd"]["list"].append("%s:%s" % (user, password))
|
||||||
self._user_data["chpasswd"]["list"] += "%s:%s\n" % (user, password)
|
self._user_data["chpasswd"]["list"] += "%s:%s\n" % (user, password)
|
||||||
|
|
||||||
def _write_userdata(self):
|
def _write_userdata(self):
|
||||||
self.add_text("/openstack/latest/user_data", "#cloud-config\n" + json.dumps(self._user_data, indent=4))
|
self.add_text("/openstack/latest/user_data", "#cloud-config\n" + json.dumps(self._user_data, indent=4))
|
||||||
|
|
||||||
def write_drive(self, path, fmt):
|
def write_iso(self, path):
|
||||||
self._write_metadata()
|
self._write_metadata()
|
||||||
self._write_userdata()
|
self._write_userdata()
|
||||||
|
|
||||||
if fmt == "iso":
|
|
||||||
self._write_iso(path)
|
|
||||||
elif fmt == "tgz":
|
|
||||||
self._write_tgz(path)
|
|
||||||
else:
|
|
||||||
raise ValueError("Unknown format")
|
|
||||||
|
|
||||||
def _write_iso(self, path):
|
|
||||||
p = subprocess.Popen([self._genisoimage,
|
p = subprocess.Popen([self._genisoimage,
|
||||||
"-J", "-r", "-q",
|
"-J", "-r", "-q",
|
||||||
"-V", "config-2",
|
"-V", "config-2",
|
||||||
|
@ -233,10 +220,6 @@ class ConfigDrive:
|
||||||
|
|
||||||
return p.wait()
|
return p.wait()
|
||||||
|
|
||||||
def _write_tgz(self, path):
|
|
||||||
p = subprocess.Popen(["tar", "cfz", path, "-C", self._tmpfs.getsyspath(""), "."])
|
|
||||||
return p.wait()
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self._tmpfs:
|
if self._tmpfs:
|
||||||
self._tmpfs.close()
|
self._tmpfs.close()
|
||||||
|
@ -249,8 +232,7 @@ class ConfigDrive:
|
||||||
# cfgdrv.add_command("rm -rf /home/debian/; userdel debian; groupdel debian", True)
|
# cfgdrv.add_command("rm -rf /home/debian/; userdel debian; groupdel debian", True)
|
||||||
# cfgdrv.add_command("cloud-init single --name cc_resolv_conf", True)
|
# cfgdrv.add_command("cloud-init single --name cc_resolv_conf", True)
|
||||||
# cfgdrv.add_command("rm -f /etc/network/interfaces.d/eth*.cfg", True)
|
# cfgdrv.add_command("rm -f /etc/network/interfaces.d/eth*.cfg", True)
|
||||||
# cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' /etc/cloud/templates/sources.list.*.tmpl; "
|
# cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' /etc/cloud/templates/sources.list.*.tmpl; rm /etc/apt/sources.list.d/*", True)
|
||||||
# "rm /etc/apt/sources.list.d/*", True)
|
|
||||||
# #cfgdrv.add_command("(whoami; date) > /root/bleep", False)
|
# #cfgdrv.add_command("(whoami; date) > /root/bleep", False)
|
||||||
# cfgdrv.add_pubkey("ssh-rsa bleep foo")
|
# cfgdrv.add_pubkey("ssh-rsa bleep foo")
|
||||||
# cfgdrv.set_password("root", "kitteh")
|
# cfgdrv.set_password("root", "kitteh")
|
||||||
|
@ -262,28 +244,16 @@ def main():
|
||||||
parser.add_argument("-H", "--hostname", required=True, help="Hostname")
|
parser.add_argument("-H", "--hostname", required=True, help="Hostname")
|
||||||
parser.add_argument("-o", "--output", required=True, help="Path to write iso to")
|
parser.add_argument("-o", "--output", required=True, help="Path to write iso to")
|
||||||
parser.add_argument("-n", "--nameservers", "--ns", default=["1.1.1.1", "8.8.8.8"], nargs="+", help="Nameservers")
|
parser.add_argument("-n", "--nameservers", "--ns", default=["1.1.1.1", "8.8.8.8"], nargs="+", help="Nameservers")
|
||||||
parser.add_argument("-i", "--networks", "--net", default=[], nargs="+",
|
parser.add_argument("-i", "--networks", "--net", default=[], nargs="+", help="Specify all networks, in format of interface[:address:[gateway]]. Both : and ; can be used as delimiter (but only one per net config). Address MUST be a network in CIDR notation")
|
||||||
help="Specify all networks, in format of interface[:address:[gateway]]. "
|
|
||||||
"Both : and ; can be used as delimiter (but only one per net config). "
|
|
||||||
"Address MUST be a network in CIDR notation")
|
|
||||||
parser.add_argument("-u", "--disable-upgrades", action="store_true", default=False)
|
parser.add_argument("-u", "--disable-upgrades", action="store_true", default=False)
|
||||||
parser.add_argument("-v", "--verbose", action="store_true", default=False)
|
parser.add_argument("-v", "--verbose", action="store_true", default=False)
|
||||||
parser.add_argument("--no-debian-cleanup", "--ndc", action="store_true", default=False)
|
parser.add_argument("--no-debian-cleanup", "--ndc", action="store_true", default=False)
|
||||||
parser.add_argument("--set-root-password", "--srp", default=None)
|
parser.add_argument("--set-root-password", "--srp", default=None)
|
||||||
parser.add_argument("-a", "--add-user", default=[], nargs="+",
|
parser.add_argument("-a", "--add-user", default=[], nargs="+", help="Add users, format is username:key?:sudo?:gecos?:password?, sudo is a bool, key is either an ssh key or a path to an ssh key")
|
||||||
help="Add users, format is username:key?:sudo?:gecos?:password?, "
|
|
||||||
"sudo is a bool, key is either an ssh key or a path to an ssh key")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if not args.format:
|
|
||||||
if args.output.endswith(".tar.gz") or args.output.endswith(".tgz"):
|
|
||||||
args.format = "tgz"
|
|
||||||
elif args.output.endswith(".iso"):
|
|
||||||
args.format = "iso"
|
|
||||||
else:
|
|
||||||
parser.error("Could not infer output format from output file extension")
|
|
||||||
|
|
||||||
cfgdrv = None
|
cfgdrv = None
|
||||||
try:
|
try:
|
||||||
cfgdrv = ConfigDrive(verbose=args.verbose)
|
cfgdrv = ConfigDrive(verbose=args.verbose)
|
||||||
|
@ -291,7 +261,10 @@ def main():
|
||||||
cfgdrv.set_hostname(args.hostname)
|
cfgdrv.set_hostname(args.hostname)
|
||||||
|
|
||||||
for net in args.networks:
|
for net in args.networks:
|
||||||
net = net.split(":")
|
if ";" in net:
|
||||||
|
net = net.split(";")
|
||||||
|
else:
|
||||||
|
net = net.split(":")
|
||||||
cfgdrv.conf_network(*net)
|
cfgdrv.conf_network(*net)
|
||||||
|
|
||||||
if args.nameservers:
|
if args.nameservers:
|
||||||
|
@ -302,10 +275,9 @@ def main():
|
||||||
|
|
||||||
if not args.no_debian_cleanup:
|
if not args.no_debian_cleanup:
|
||||||
cfgdrv.add_command("rm -f /etc/network/interfaces.d/eth*", True)
|
cfgdrv.add_command("rm -f /etc/network/interfaces.d/eth*", True)
|
||||||
cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' /etc/cloud/templates/sources.list.*.tmpl; "
|
cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' /etc/cloud/templates/sources.list.*.tmpl; rm /etc/apt/sources.list.d/*", True)
|
||||||
"rm /etc/apt/sources.list.d/*", True)
|
cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' /etc/resolv.conf /etc/cloud/templates/resolv.conf.tmpl", True)
|
||||||
cfgdrv.add_command("sed -rni '/^([^#]|## template)/p' "
|
|
||||||
"/etc/resolv.conf /etc/cloud/templates/resolv.conf.tmpl", True)
|
|
||||||
|
|
||||||
if args.set_root_password:
|
if args.set_root_password:
|
||||||
cfgdrv.set_password("root", args.set_root_password)
|
cfgdrv.set_password("root", args.set_root_password)
|
||||||
|
@ -339,11 +311,11 @@ def main():
|
||||||
cfgdrv.add_user(user[0], keys, sudo=sudo, gecos=gecos, password=password)
|
cfgdrv.add_user(user[0], keys, sudo=sudo, gecos=gecos, password=password)
|
||||||
|
|
||||||
if args.output:
|
if args.output:
|
||||||
cfgdrv.write_iso(args.output)
|
ret = cfgdrv.write_iso(args.output)
|
||||||
|
sys.exit(ret)
|
||||||
finally:
|
finally:
|
||||||
if cfgdrv:
|
if cfgdrv:
|
||||||
cfgdrv.close()
|
cfgdrv.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
20
setup.py
20
setup.py
|
@ -1,20 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from distutils.core import setup
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name='genconfdrv',
|
|
||||||
version='0.1.0',
|
|
||||||
description='',
|
|
||||||
author='Sebastian Lohff',
|
|
||||||
author_email='seba@someserver.de',
|
|
||||||
url='https://git.someserver.de/seba/genconfdrv/',
|
|
||||||
python_requires='>=3.5',
|
|
||||||
packages=['genconfdrv'],
|
|
||||||
install_requires=['fs'],
|
|
||||||
entry_points={
|
|
||||||
'console_scripts': [
|
|
||||||
'genconfdrv = genconfdrv.genconfdrv:main'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
)
|
|
Loading…
Reference in New Issue