diff --git a/systemvm/patches/debian/config/opt/cloud/bin/configure.py b/systemvm/patches/debian/config/opt/cloud/bin/configure.py index 00eadcf7e1c..ac961b4c33c 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/configure.py +++ b/systemvm/patches/debian/config/opt/cloud/bin/configure.py @@ -544,7 +544,7 @@ class CsIP: if "public_ip" in self.address: return self.address['public_ip'] return "unknown" - + def post_config_change(self, method): route = CsRoute(self.dev) @@ -634,6 +634,169 @@ class CsIP: self.post_config_change("delete") +class CsVmMetadata(): + def __init__(self): + self.data = {} + db = dataBag() + db.setKey("vmdata") + db.load() + self.dbag = db.getDataBag() + + def process(self): + for ip in self.dbag: + if ("id" == ip): + continue + logging.info("Processing metadata for %s" % ip) + for item in self.dbag[ip]: + folder = item[0] + file = item[1] + data = item[2] + + # process only valid data + if folder != "userdata" and folder != "metadata": + continue + + if file == "": + continue + + self.__htaccess(ip, folder, file) + + if data == "": + self.__deletefile(ip, folder, file) + else: + self.__createfile(ip, folder, file, data) + + def __deletefile(self, ip, folder, file): + datafile = "/var/www/html/" + folder + "/" + ip + "/" + file + + if os.path.exists(datafile): + os.remove(datafile) + + def __createfile(self, ip, folder, file, data): + dest = "/var/www/html/" + folder + "/" + ip + "/" + file + metamanifestdir = "/var/www/html/" + folder + "/" + ip + metamanifest = metamanifestdir + "/meta-data" + + # base64 decode userdata + if folder == "userdata" or folder == "user-data": + if data is not None: + data = base64.b64decode(data) + + fh = open(dest, "w") + self.__exflock(fh) + if data is not None: + fh.write(data) + else: + fh.write("") + self.__unflock(fh) + fh.close() + os.chmod(dest, 0644) + + if folder == "metadata" or folder == "meta-data": + try: + os.makedirs(metamanifestdir, 0755) + except OSError as e: + # error 17 is already exists, we do it this way for concurrency + if e.errno != 17: + print "failed to make directories " + metamanifestdir + " due to :" +e.strerror + sys.exit(1) + if os.path.exists(metamanifest): + fh = open(metamanifest, "r+a") + self.__exflock(fh) + if not file in fh.read(): + fh.write(file + '\n') + self.__unflock(fh) + fh.close() + else: + fh = open(metamanifest, "w") + self.__exflock(fh) + fh.write(file + '\n') + self.__unflock(fh) + fh.close() + + if os.path.exists(metamanifest): + os.chmod(metamanifest, 0644) + + def __htaccess(self, ip, folder, file): + entry = "RewriteRule ^" + file + "$ ../" + folder + "/%{REMOTE_ADDR}/" + file + " [L,NC,QSA]" + htaccessFolder = "/var/www/html/latest" + htaccessFile = htaccessFolder + "/.htaccess" + + try: + os.mkdir(htaccessFolder,0755) + except OSError as e: + # error 17 is already exists, we do it this way for concurrency + if e.errno != 17: + print "failed to make directories " + htaccessFolder + " due to :" +e.strerror + sys.exit(1) + + if os.path.exists(htaccessFile): + fh = open(htaccessFile, "r+a") + self.__exflock(fh) + if not entry in fh.read(): + fh.write(entry + '\n') + self.__unflock(fh) + fh.close() + else: + fh = open(htaccessFile, "w") + self.__exflock(fh) + fh.write("Options +FollowSymLinks\nRewriteEngine On\n\n") + fh.write(entry + '\n') + self.__unflock(fh) + fh.close() + + entry="Options -Indexes\nOrder Deny,Allow\nDeny from all\nAllow from " + ip + htaccessFolder = "/var/www/html/" + folder + "/" + ip + htaccessFile = htaccessFolder+"/.htaccess" + + try: + os.makedirs(htaccessFolder,0755) + except OSError as e: + # error 17 is already exists, we do it this way for sake of concurrency + if e.errno != 17: + print "failed to make directories " + htaccessFolder + " due to :" +e.strerror + sys.exit(1) + + fh = open(htaccessFile, "w") + self.__exflock(fh) + fh.write(entry + '\n') + self.__unflock(fh) + fh.close() + + if folder == "metadata" or folder == "meta-data": + entry = "RewriteRule ^meta-data/(.+)$ ../" + folder + "/%{REMOTE_ADDR}/$1 [L,NC,QSA]" + htaccessFolder = "/var/www/html/latest" + htaccessFile = htaccessFolder + "/.htaccess" + + fh = open(htaccessFile, "r+a") + self.__exflock(fh) + if not entry in fh.read(): + fh.write(entry + '\n') + + entry = "RewriteRule ^meta-data/$ ../" + folder + "/%{REMOTE_ADDR}/meta-data [L,NC,QSA]" + + fh.seek(0) + if not entry in fh.read(): + fh.write(entry + '\n') + self.__unflock(fh) + fh.close() + + def __exflock(self, file): + try: + flock(file, LOCK_EX) + except IOError as e: + print "failed to lock file" + file.name + " due to : " + e.strerror + sys.exit(1) #FIXME + return True + + def __unflock(self, file): + try: + flock(file, LOCK_UN) + except IOError: + print "failed to unlock file" + file.name + " due to : " + e.strerror + sys.exit(1) #FIXME + return True + def main(argv): logging.basicConfig(filename='/var/log/cloud.log', @@ -666,5 +829,8 @@ def main(argv): ip.configure() CsPassword() + metadata = CsVmMetadata() + metadata.process() + if __name__ == "__main__": main(sys.argv) diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs_vmdata.py b/systemvm/patches/debian/config/opt/cloud/bin/cs_vmdata.py new file mode 100644 index 00000000000..32679caf123 --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/cs_vmdata.py @@ -0,0 +1,5 @@ +from pprint import pprint + +def merge(dbag, metadata): + dbag[metadata["vm_ip_address"]] = metadata["vm_metadata"] + return dbag \ No newline at end of file diff --git a/systemvm/patches/debian/config/opt/cloud/bin/merge.py b/systemvm/patches/debian/config/opt/cloud/bin/merge.py index c66eafed5cd..65957d128ba 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/merge.py +++ b/systemvm/patches/debian/config/opt/cloud/bin/merge.py @@ -9,6 +9,7 @@ import cs_guestnetwork import cs_cmdline import cs_vmp import cs_network_acl +import cs_vmdata from pprint import pprint @@ -78,6 +79,8 @@ class updateDataBag: dbag = self.processVMpassword(self.db.getDataBag()) elif self.qFile.type == 'networkacl': dbag = self.process_network_acl(self.db.getDataBag()) + elif self.qFile.type == 'vmdata': + dbag = self.processVmData(self.db.getDataBag()) else: logging.error("Error I do not know what to do with file of type %s", self.qFile.type) return @@ -138,6 +141,10 @@ class updateDataBag: dp['nw_type'] = 'control' qf = loadQueueFile() qf.load({ 'ip_address' : [ dp ], 'type' : 'ips'}) + + def processVmData(self, dbag): + cs_vmdata.merge(dbag, self.qFile.data) + return dbag class loadQueueFile: