def create_volume(self, **args): if "name" not in args or not args["name"]: return {"message": "Volume name not specified", "code": 1} name = args["name"] if "instance_name" not in args or not args["instance_name"]: return {"message": "Domain name not specified", "code": 1} instance_name = args["instance_name"] if "volume_size" not in args \ or not args["volume_size"] \ or not isinstance(args["volume_size"], int): return {"message": "Volume size(GB) not specified", "code": 1} volume_size = args["volume_size"] image = args.get("image", None) volume_config = self.prepare_volume(name, image, volume_size) if not len(volume_config): return { "message": "Fail to craete volume %s, read log file for details" % name, "code": 1 } target = "%s%s%s%s.xml" % (config.instance_data, instance_name, os.sep, name) utils.persist(volume_config, target) return {"message": "Volume %s created" % name, "code": 0}
def attach_volume(self, **args): if "instance_name" not in args or not args["instance_name"]: return {"message": "Domain name not specified", "code": 1} instance_name = args["instance_name"] domain_exists = utils.domain_exists(instance_name) if not domain_exists: return { "message": "Domain %s not found" % instance_name, "code": 1 } stat = utils.domain_stat(instance_name) live = "shut off" not in stat if "name" not in args or not args["name"]: return {"message": "Volume name not specified", "code": 1} name = args["name"] target = "%s%s%s%s.xml" % (config.instance_data, instance_name, os.sep, name) if not os.path.exists(target): return {"message": "Volume %s xml not found" % name, "code": 1} volume_config = open(target).read() log.debug("Volume: %s" % volume_config) if "TARGET" in volume_config: device = utils.get_available_blk_target(instance_name) volume_config, count = re.subn("'vd[a-z]'|'TARGET'", "'%s'" % device, volume_config) log.debug(volume_config) utils.persist(volume_config, target) virshcmd = "virsh attach-device \ --domain %s --file %s \ --config %s" % (instance_name, target, "--live" if live else "") pipe = Popen(virshcmd, shell=True, stdout=PIPE, stderr=PIPE) err = pipe.stderr.read() info = pipe.stdout.read() log.debug("Attach Disk with command '%s', and system output:'%s %s'" % (virshcmd, err, info)) if info and "Device attached successfully" in info: return { "message": "Volume %s attached to domain %s" % (name, instance_name), "code": 0 } else: return { "message": "Fail to attach %s to domain %s" % (name, instance_name), "code": 1 }
def persist_meta_data(self, hostname, domain, domain_id): self.meta_data["hostname"] = hostname self.meta_data["launch_index"] = 0 self.meta_data["name"] = domain self.meta_data["uuid"] = domain_id if domain_id else str(uuid.uuid4()) self.meta_data["files"] = self.content_files utils.persist(json.dumps(self.meta_data), "%s%s%s%s%s%s%s" % (self.config_drive_tree, os.sep, "openstack", os.sep, "latest", os.sep, "meta_data.json"))
def attach_cdrom(self, **args): if "name" not in args or not args["name"]: return {"message": 1, "code": "Domain name not specified !"} domain = args["name"] if not utils.domain_exists(domain): return {"message": 1, "code": "Domain %s not found !" % domain} if "iso_file" not in args or not args["iso_file"]: return {"message": "ISO file not specified !", "code": 1} iso_file = args["iso_file"] if not utils.ceph_blk_exists(config.ceph_iso_pool, iso_file, config.ceph_iso_pool_user): return { "message": "File %s not uploaded to pool %s" % (iso_file, config.ceph_iso_pool), "code": 1 } if "iso_type" not in args: return { "message": "ISO file type not specified: 0 for PE,1 for Oracle/MSSQL,etc", "code": 1 } iso_type = args["iso_type"] cdrom_xml = utils.assemble_cdrom_xml(config.ceph_iso_pool, iso_file) target = "%s%s%s%s.xml" % (config.instance_data, domain, os.sep, iso_file) utils.persist(cdrom_xml, target) if not self.__update_cdrom(domain, target): return { "message": "Cannot attach iso, read log for more details .", "code": 1 } if iso_type > 0: return {"message": "SUCCESS", "code": 0} result = utils.reset_cdrom_index(domain, 0) if not result: return { "message": "Fail to reset boot order for CDROM, read log for details.", "code": 1 } return {"message": "SUCCESS", "code": 0}
def attach_volume(self, **args): if "instance_name" not in args or not args["instance_name"]: return {"message": "Domain name not specified", "code": 1} instance_name = args["instance_name"] domain_exists = utils.domain_exists(instance_name) if not domain_exists: return {"message": "Domain %s not found" % instance_name, "code": 1} stat = utils.domain_stat(instance_name) live = "shut off" not in stat if "name" not in args or not args["name"]: return {"message": "Volume name not specified", "code": 1} name = args["name"] target = "%s%s%s%s.xml" % (config.instance_data, instance_name, os.sep, name) if not os.path.exists(target): return {"message": "Volume %s xml not found" % name, "code": 1} volume_config = open(target).read() log.debug("Volume: %s" % volume_config) if "TARGET" in volume_config: device = utils.get_available_blk_target(instance_name) volume_config, count = re.subn("'vd[a-z]'|'TARGET'", "'%s'" % device, volume_config) log.debug(volume_config) utils.persist(volume_config, target) virshcmd = "virsh attach-device \ --domain %s --file %s \ --config %s" % (instance_name, target, "--live" if live else "") pipe = Popen(virshcmd, shell=True, stdout=PIPE, stderr=PIPE) err = pipe.stderr.read() info = pipe.stdout.read() log.debug("Attach Disk with command '%s', and system output:'%s %s'" % (virshcmd, err, info)) if info and "Device attached successfully" in info: return {"message": "Volume %s attached to domain %s" % (name, instance_name), "code": 0} else: return {"message": "Fail to attach %s to domain %s" % (name, instance_name), "code": 1}
def detach_cdrom(self, **args): if "name" not in args or not args["name"]: return {"message": 1, "code": "Domain name not specified !"} domain = args["name"] if not utils.domain_exists(domain): return {"message": 1, "code": "Domain %s not found !" % domain} empty_cdrom = utils.assemble_cdrom_xml(None, None) target = "/tmp/empty_cdrom.xml" utils.persist(empty_cdrom, target) if not self.__update_cdrom(domain, target): return {"message": "Fail to detach cdrom", "code": 1} cdrom_first = utils.cdrom_in_first_order(domain) if cdrom_first: result = utils.reset_cdrom_index(domain, 1) if not result: return {"message": "Fail to restore boot order", "code": 1} return {"message": "SUCCESS", "code": 0}
def update_content_with_networks(self, networks): # NOTE: # Now, config drive content only provides Domain ifcfg-XX file copying # In future, hosts/resolve/yum.conf and so on , can be injected if not getattr(self, "content_files"): self.content_files = [] for dev, dev_conf in networks.iteritems(): item = {} item["path"] = "%s%s" % (config.NETWORK_CONF_PREFIX["RH"], dev) content_index = len(self.content_files) item["content_path"] = \ "/content/%s" % self.__num_trans(content_index) self.content_files.append(item) dev_conf = self.assemble_dev_config(dev, **dev_conf) dev_content_file = "%s%s%s%s" % (self.config_drive_tree, os.sep, "openstack", item["content_path"]) utils.persist(dev_conf, dev_content_file) return self.content_files
def create_volume(self, **args): if "name" not in args or not args["name"]: return {"message": "Volume name not specified", "code": 1} name = args["name"] if "instance_name" not in args or not args["instance_name"]: return {"message": "Domain name not specified", "code": 1} instance_name = args["instance_name"] if "volume_size" not in args \ or not args["volume_size"] \ or not isinstance(args["volume_size"], int): return {"message": "Volume size(GB) not specified", "code": 1} volume_size = args["volume_size"] image = args.get("image", None) volume_config = self.prepare_volume(name, image, volume_size) if not len(volume_config): return {"message": "Fail to craete volume %s, read log file for details" % name, "code": 1} target = "%s%s%s%s.xml" % (config.instance_data, instance_name, os.sep, name) utils.persist(volume_config, target) return {"message": "Volume %s created" % name, "code": 0}
def persist_user_data(self): self.user_data = "%s%s" % (self.user_data, "#!/bin/bash\n") # NOTE: # In user_data script, it's import to arrange # specified action around appropriate EVENT . # e.g: # It's fit that you start your haproxy process after # domain network restarted and IPs configured self.set_admin_pass() self.set_network() # e.g: unarchive httpd.tar.gz # e.g: install httpd.rpm & dependency packages # e.g: copy user website to httpd wwwroot & chmod # e.g: start httpd service # e.g: set firewall and expose service port # # In future, 'ACTION GROUPs' will be added and executed in sequence # this's very similar to Iptable Chains and Chain rules # e.g: # Basic_Settings = ('set_adminPass', 'set_hosts', # 'set_hostname', 'set_yum', ...) # Rpm_Install = ('install_httpd', 'install_haproxy', ...) # Service_Settings = ('init_mariadb', 'deploy_httpd', ...) # Service_Starting = ('start_httpd', 'start_hginx', ...) # Expose_Service_Ports = ('enable_http_access', # 'enable_nginx_access', ...) # # For simplicity, this method only provides functions: # (1) set adminPass # (2) restart network utils.persist("%s" % self.user_data, "%s%s%s%s%s%s%s" % (self.config_drive_tree, os.sep, "openstack", os.sep, "latest", os.sep, "user_data"))
def create_config_drive_tree(domain): # The following diagram shows the standard # file tree of ConfigDrive that CloudInit can # read and parse: # # openstack # ├- content # └- latest # ├── meta_data.json # ├── user_data # └ vendor_data.json # # (1) content: storing files to be copied to domain from config drive,eg: # nic configurations(ifcfg-eth0), hosts, softwares, etc # (2) meta_data.json: storing domain metadata, e.g: hostname, uuid, name # (3) user_data: /python/shell/powershell/bat scripts # (4) vendor_data.json: default {} is ok domain_drive = "%s%s" % (config.config_drives, domain) if os.path.exists(domain_drive): __import__("shutil").rmtree(domain_drive) os.makedirs(domain_drive) topdir = "%s%s%s" % (domain_drive, os.sep, "openstack") file_store = "%s%s%s" % (topdir, os.sep, "content") os.makedirs(file_store) conf_store = "%s%s%s" % (topdir, os.sep, "latest") os.makedirs(conf_store) meta_target = "%s%s%s" % (conf_store, os.sep, "meta_data.json") utils.persist("{}", meta_target) userd_target = "%s%s%s" % (conf_store, os.sep, "user_data") utils.persist("# user data scripts\n", userd_target) vendor_target = "%s%s%s" % (conf_store, os.sep, "vendor_data.json") utils.persist("{}", vendor_target) return domain_drive
def create_instance(self, **args): if "name" not in args or not args["name"]: return {"code": 1, "message": "Domain name not specified !"} name = args["name"] domain_exists = utils.domain_exists(name) if domain_exists: return {"code": 1, "message": "Domain %s already exists!" % name} self.instance_base_dir = "%s%s%s" % (self.instance_data, name, os.sep) self.__ensure_instance_dir(self.instance_base_dir) if "image" not in args or not args["image"]: return {"code": 1, "message": "Image name not specified !"} image_name = args["image"] if not self.__image_exists(image_name): return { "code": 1, "message": "Contact Administrator to upload image %s" % image_name } possible_os_type = image_name.lower().count("win") clock_offset = config.clock_offset_windows if possible_os_type else config.clock_offset_linux """ Prepare system volume """ boot_volume = config.volume_name_format % { "domain": name, "type": config.volume_type_boot, "uuid": uuid.uuid4() } volumexml = self.__prepare_volume(name=boot_volume, image=image_name) """ As bootable volume, blk target should be set to 'vda' """ volumexml = volumexml.replace("TARGET", "vda") persist_volume = "%s%s.xml" % (self.instance_base_dir, boot_volume) utils.persist(volumexml, persist_volume) build_link_result = self.__build_network_links(name) if not build_link_result: return { "code": 1, "message": "Fail to build links for domain %s" % name } instance_template = self.__read_instance_template() if len(instance_template) == 0: return {"code": 1, "message": "Tempalte file error"} if "vcpu" not in args or "memory" not in args: return { "code": 1, "message": "Domain flavor(vcpu,memory) not specified" } # MB -> KB memory = args["memory"] * 1024 vcpu = args["vcpu"] instance_template = self.__init_domain_params(instance_template, name, vcpu, memory, clock_offset, volumexml) virshxml = self.__persist_virshxml(instance_template, name) def define_domain_from_xml(xml): virshcmd = "virsh define %s" % xml output = Popen(virshcmd, shell=True, stdout=PIPE).stdout.read() log.info("Define domain %s with %s:%s" % (name, xml, output)) define_domain_from_xml(virshxml) def start(name): virshcmd = "virsh start %s" % name output = Popen(virshcmd, shell=True, stdout=PIPE).stdout.read() log.info("Boot domain %s:%s" % (name, output)) start(name) return {"code": 0, "message": "Domain %s booting " % name}
def __persist_virshxml(self, xml, domain): target = "%s%s.xml" % (self.instance_base_dir, domain) utils.persist(xml, target) return target
def test_persist(content, target): utils.persist(content, target)