def hypervisorOpenDialog(self, parent): logging.debug("hypervisorOpenDialog(): Instantiated") self.parent = parent self.s = SystemConfigIO() result = self.openHypervisor(self.s.getConfig()["VBOX"]["VBOX_PATH"]) logging.debug("hypervisorOpenDialog(): Completed") return result
def __init__(self, parent, configname, actionname, experimentHostname, rdpBrokerHostname="<unspecified>", users_file="", itype="", name=""): logging.debug("ConnectionActionDialog(): instantiated") super(ConnectionActionDialog, self).__init__(parent) self.parent = parent self.eco = ExperimentConfigIO.getInstance() self.s = SystemConfigIO() self.configname = configname self.actionname = actionname self.experimentHostname = experimentHostname self.usersFile = users_file self.itype = itype self.name = name if rdpBrokerHostname.strip() == "": self.rdpBrokerHostname = "<unspecified>" self.setEnabled(False) else: self.rdpBrokerHostname = rdpBrokerHostname self.cm = ConnectionManage() self.setMinimumWidth(450) self.createFormGroupBox() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle(str(actionname) + " Connection")
def experimentAddDialog(self, parent, existingconfignames): logging.debug("experimentAddDialog(): Instantiated") self.parent = parent self.s = SystemConfigIO() self.destinationPath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH']) self.configname, ok = QInputDialog.getText( parent, 'Experiment', 'Enter new experiment name \r\n(non alphanumeric characters will be removed)' ) if ok: #standardize and remove invalid characters self.configname = ''.join(e for e in self.configname if e.isalnum()) #check to make sure the name doesn't already exist if self.configname in existingconfignames: QMessageBox.warning( self.parent, "Name Exists", "The experiment name specified already exists", QMessageBox.Ok) return None ##Otherwise, create the folders for this and return the name so that it can be added to the main GUI window successfilenames = self.addExperiment() logging.debug("experimentAddDialog(): Completed") if len(successfilenames) > 0: return self.configname return None
def experimentActionDialog(self, configname, actionname, itype="", name=""): logging.debug("experimentActionDialog(): Instantiated") self.configname = configname self.s = SystemConfigIO() self.destinationPath = os.path.join(self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH']) ouputstr = self.experimentAction(actionname, itype, name) logging.debug("experimentActionDialog(): Completed") return ouputstr
def __init__(self, vmManage, experimentManage): logging.debug("PackageManageVBox(): instantiated") PackageManage.__init__(self) self.vmManage = vmManage self.em = experimentManage self.s = SystemConfigIO() self.s.readConfig()
def materialRemoveFileDialog(self, configname, materialname): logging.debug("materialRemoveFileDialog(): Instantiated") self.configname = configname self.materialname = materialname self.s = SystemConfigIO() self.destinationPath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], self.configname, "Materials") successfilenames = self.removeMaterial(materialname) logging.debug("materialRemoveFileDialog(): Completed") return successfilenames
def __init__(self, initializeVMManage=True): logging.info("VBoxManage.__init__(): instantiated") VMManage.__init__(self) self.cf = SystemConfigIO() self.vmanage_path = self.cf.getConfig()['VBOX']['VMANAGE_PATH'] # A lock for acces/updates to self.vms self.lock = RLock() self.vms = {} self.tempVMs = {} if initializeVMManage: self.refreshAllVMInfo() result = self.getManagerStatus()["writeStatus"] while result != self.MANAGER_IDLE: #waiting for manager to finish query... result = self.getManagerStatus()["writeStatus"] time.sleep(.1)
class MaterialAddFileDialog: def materialAddFileDialog(self, configname): logging.debug("materialAddFileDialog(): Instantiated") self.configname = configname self.s = SystemConfigIO() self.destinationPath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], self.configname, "Materials") widget = QFileDialog() filenames = "" filenames, _ = QFileDialog.getOpenFileNames(widget, "Choose Material", "") if len(filenames) > 1: successfilenames = self.copyMaterial(filenames) return successfilenames elif len(filenames) == 1: successfilenames = self.copyMaterial(filenames) return successfilenames else: return [] logging.debug("materialAddFileDialog(): Completed") def copyMaterial(self, filenames): logging.debug("copyMaterial(): instantiated") #self.status = {"vmName" : self.vmName, "adaptorSelected" : self.adaptorSelected} #get the first value in adaptorSelected (should always be a number) status, successfilenames = MaterialAddingFileDialog( None, filenames, self.destinationPath).exec_() return successfilenames
def __init__(self, parent): logging.debug("ConfigurationDialog(): instantiated") super(ConfigurationDialog, self).__init__(parent) self.parent = parent self.s = SystemConfigIO() self.setMinimumWidth(435) self.createFormGroupBox() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("RES Configuration")
def materialAddFileDialog(self, configname): logging.debug("materialAddFileDialog(): Instantiated") self.configname = configname self.s = SystemConfigIO() self.destinationPath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], self.configname, "Materials") widget = QFileDialog() filenames = "" filenames, _ = QFileDialog.getOpenFileNames(widget, "Choose Material", "") if len(filenames) > 1: successfilenames = self.copyMaterial(filenames) return successfilenames elif len(filenames) == 1: successfilenames = self.copyMaterial(filenames) return successfilenames else: return [] logging.debug("materialAddFileDialog(): Completed")
def __init__(self, parent): logging.debug("VMRetrieveDialog(): instantiated") super(VMRetrieveDialog, self).__init__(parent) self.parent = parent self.s = SystemConfigIO() self.vms = {} self.vmNames = [] self.buttons = QDialogButtonBox() self.ok_button = self.buttons.addButton(self.buttons.Ok) self.ok_button.setEnabled(False) self.buttons.addButton(self.buttons.Cancel) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) self.setWindowTitle("Add Virtual Machines") #self.setFixedSize(550, 300) self.box_main_layout = QGridLayout() self.box_main = QWidget() self.box_main.setLayout(self.box_main_layout) label = QLabel("Select VMs to add") self.box_main_layout.addWidget(label, 1, 0) self.setLayout(self.box_main_layout) ##### # Here we will place the tree view self.treeWidget = VMTreeWidget(self) self.treeWidget.itemSelectionChanged.connect(self.onItemSelected) self.box_main_layout.addWidget(self.treeWidget, 1, 0) s = VMRetrievingDialog(self.parent).exec_() self.vms = s["vmstatus"] if len(self.vms) == 0: logging.error("No VMs were retrieved") noVMsDialog = QMessageBox.critical( self, "VM Error", "No VMs were found. If you think this is incorrect, please check the path to VBoxManage in config/config.ini and then restart the program.", QMessageBox.Ok) #self.treeWidget.setSelectionMode(VMTreeWidget.MultiSelection) self.treeWidget.populateTreeStore(self.vms) #self.treeWidget.adjustSize() #self.adjustSize() ##### self.box_main_layout.addWidget(self.buttons, 2, 0) self.setLayout(self.box_main_layout)
class HypervisorOpenDialog: def hypervisorOpenDialog(self, parent): logging.debug("hypervisorOpenDialog(): Instantiated") self.parent = parent self.s = SystemConfigIO() result = self.openHypervisor(self.s.getConfig()["VBOX"]["VBOX_PATH"]) logging.debug("hypervisorOpenDialog(): Completed") return result def openHypervisor(self, pathToHypervisor): logging.debug("openHypervisor(): instantiated") result = HypervisorOpeningDialog(self.parent, pathToHypervisor).exec_() return result
def __init__(self): #Virtually private constructor self.s = SystemConfigIO() self.rolledoutjson = {} self.config_jsondata = {} self.config_rdp_userpass = {}
class ExperimentConfigIO: __singleton_lock = threading.Lock() __singleton_instance = None @classmethod def getInstance(cls): logging.debug("getInstance() ExperimentConfigIO: instantiated") if not cls.__singleton_instance: with cls.__singleton_lock: if not cls.__singleton_instance: cls.__singleton_instance = cls() return cls.__singleton_instance def __init__(self): #Virtually private constructor self.s = SystemConfigIO() self.rolledoutjson = {} self.config_jsondata = {} self.config_rdp_userpass = {} def storeConfigRDPBrokerCreds(self, configname, username, password, url, method): logging.debug( "ExperimentConfigIO: getExperimentXMLFileData(): instantiated") self.config_rdp_userpass[configname] = (username, password, url, method) def getConfigRDPBrokerCreds(self, configname): logging.debug( "ExperimentConfigIO: getExperimentXMLFileData(): instantiated") if configname in self.config_rdp_userpass: return self.config_rdp_userpass[configname] return None def getExperimentXMLFileData(self, configname, force_refresh=False): logging.debug( "ExperimentConfigIO: getExperimentXMLFileData(): instantiated") if configname in self.config_jsondata: if force_refresh == False: return self.config_jsondata[configname] try: xmlconfigfile = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], configname, "Experiments", configname + ".xml") with open(xmlconfigfile) as fd: jsondata = xmltodict.parse(fd.read(), process_namespaces=True) self.config_jsondata[configname] = jsondata return jsondata except FileNotFoundError: logging.error( "Error in getExperimentXMLFileData(): File not found: " + str(xmlconfigfile)) return None except Exception: logging.error( "Error in getExperimentXMLFileData(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None def getExperimentServerInfo(self, configname): logging.debug( "ExperimentConfigIO: getExperimentXMLFileData(): instantiated") jsondata = self.getExperimentJSONFileData(configname) vmserverip = None rdpbroker = None chatserver = None users_file = None if "xml" in jsondata: if "testbed-setup" in jsondata["xml"]: if "network-config" in jsondata["xml"]["testbed-setup"]: if "vm-server-ip" in jsondata["xml"]["testbed-setup"][ "network-config"]: vmserverip = jsondata["xml"]["testbed-setup"][ "network-config"]["vm-server-ip"] if "rdp-broker-ip" in jsondata["xml"]["testbed-setup"][ "network-config"]: rdpbroker = jsondata["xml"]["testbed-setup"][ "network-config"]["rdp-broker-ip"] if "chat-server-ip" in jsondata["xml"]["testbed-setup"][ "network-config"]: chatserver = jsondata["xml"]["testbed-setup"][ "network-config"]["chat-server-ip"] if "vm-set" in jsondata["xml"]["testbed-setup"]: if "vm-set" in jsondata["xml"]["testbed-setup"]: if "users-filename" in jsondata["xml"][ "testbed-setup"]["vm-set"]: users_file = jsondata["xml"]["testbed-setup"][ "vm-set"]["users-filename"] return vmserverip, rdpbroker, chatserver, users_file def getExperimentVMRolledOut(self, configname, config_jsondata=None, force_refresh="False"): logging.debug( "ExperimentConfigIO: getExperimentXMLFileData(): instantiated") try: if configname in self.rolledoutjson: if force_refresh == False: return self.rolledoutjson[configname] vmRolledOutList = {} if config_jsondata == None or force_refresh: config_jsondata = self.getExperimentXMLFileData( configname, force_refresh=True) vmServerIP = config_jsondata["xml"]["testbed-setup"][ "network-config"]["vm-server-ip"] rdpBrokerIP = config_jsondata["xml"]["testbed-setup"][ "network-config"]["rdp-broker-ip"] chatServerIP = config_jsondata["xml"]["testbed-setup"][ "network-config"]["chat-server-ip"] vmSet = config_jsondata["xml"]["testbed-setup"]["vm-set"] pathToVirtualBox = config_jsondata["xml"]["vbox-setup"][ "path-to-vboxmanage"] numClones = int(vmSet["num-clones"]) cloneSnapshots = vmSet["clone-snapshots"] linkedClones = vmSet["linked-clones"] baseGroupname = vmSet["base-groupname"] baseOutname = vmSet["base-outname"] vrdpBaseport = vmSet["vrdp-baseport"] usersFilename = vmSet["users-filename"] logging.debug("getExperimentVMRolledOut(): path: " + str(pathToVirtualBox) + " numClones: " + str(numClones) + " linked: " + str(linkedClones) + " baseGroup: " + str(baseGroupname) + " baseOut: " + str(baseOutname) + "vrdpBase: " + str(vrdpBaseport) + " usersFilename: " + str(usersFilename)) if isinstance(vmSet["vm"], list) == False: logging.debug( "getExperimentVMRolledOut(): vmSet only has a single VM; placing into list for compatibility" ) vmSet["vm"] = [vmSet["vm"]] #we get the vms in order of group; for vm in vmSet["vm"]: vmName = vm["name"] vmRolledOutList[vmName] = [] logging.debug( "getExperimentVMRolledOut(): adding data for vm: " + str(vmName)) startupCmds_reformatted = None startupDelay = 0 #read startup commands if "startup" in vm and "cmd" in vm["startup"]: startupCmds_reformatted = {} if "delay" in vm["startup"]: startupDelay = vm["startup"]["delay"] startupcmds = vm["startup"]["cmd"] #if this is not a list, make it one (xml to json limitation) if isinstance(startupcmds, list) == False: startupcmds = [startupcmds] #iterate through each startup command for startupcmd in startupcmds: #if exec does not exist, just quit; can't do anything without it if "exec" not in startupcmd: logging.error( "getExperimentVMRolledOut(): exec tag missing: " + str(startupcmd)) continue #set default hypervisor and seq if they aren't specified hypervisor = "vbox" seq = "0" if hypervisor in startupcmd: hypervisor = startupcmd["hypervisor"] if "seq" in startupcmd: seq = startupcmd["seq"] #store the data and allow for duplicate sequences (store as list) if seq not in startupCmds_reformatted: startupCmds_reformatted[seq] = [ (hypervisor, startupcmd["exec"]) ] else: startupCmds_reformatted[seq].append[( hypervisor, startupcmd["exec"])] #get names for clones myBaseOutname = baseOutname for i in range(1, numClones + 1): cloneVMName = vmName + myBaseOutname + str(i) cloneGroupName = "/" + baseGroupname + "/Set" + str(i) # intnet adaptors internalnets = vm["internalnet-basename"] cloneNetNum = 1 logging.debug( "getExperimentVMRolledOut(): Internal net names: " + str(internalnets)) cloneNets = [] if isinstance(internalnets, list) == False: internalnets = [internalnets] for internalnet in internalnets: cloneNets.append( str(internalnet) + str(myBaseOutname) + str(i)) cloneNetNum += 1 # vrdp setup, if enabled include the port in the returned json vrdpEnabled = vm["vrdp-enabled"] if vrdpEnabled != None and vrdpEnabled == 'true': vrdpBaseport = str(int(vrdpBaseport)) vmRolledOutList[vmName].append({ "name": cloneVMName, "group-name": cloneGroupName, "networks": cloneNets, "vrdpEnabled": vrdpEnabled, "vrdpPort": vrdpBaseport, "baseGroupName": baseGroupname, "groupNum": str(i), "vm-server-ip": vmServerIP, "rdp-broker-ip": rdpBrokerIP, "chat-server-ip": chatServerIP, "clone-snapshots": cloneSnapshots, "linked-clones": linkedClones, "startup-cmds": startupCmds_reformatted, "startup-cmds-delay": startupDelay, "users-filename": usersFilename }) #vmRolledOutList[vmName].append({"name": cloneVMName, "group-name": cloneGroupName, "networks": cloneNets, "vrdpEnabled": vrdpEnabled, "vrdpPort": vrdpBaseport, "baseGroupName": baseGroupname, "groupNum": str(i), "vm-server-ip": vmServerIP, "clone-snapshots": cloneSnapshots, "linked-clones": linkedClones, "startup-cmds": startupCmds_reformatted, "startup-cmds-delay": startupDelay, "users-filename": usersFilename}) vrdpBaseport = int(vrdpBaseport) + 1 #otherwise, don't include vrdp port else: #vmRolledOutList[vmName].append({"name": cloneVMName, "group-name": cloneGroupName, "networks": cloneNets, "vrdpEnabled": vrdpEnabled, "baseGroupName": baseGroupname, "groupNum": str(i), "clone-snapshots": cloneSnapshots, "linked-clones": linkedClones, "startup-cmds": startupCmds_reformatted, "startup-cmds-delay": startupDelay, "users-filename": usersFilename}) vmRolledOutList[vmName].append({ "name": cloneVMName, "group-name": cloneGroupName, "networks": cloneNets, "vrdpEnabled": vrdpEnabled, "baseGroupName": baseGroupname, "groupNum": str(i), "vm-server-ip": vmServerIP, "clone-snapshots": cloneSnapshots, "linked-clones": linkedClones, "startup-cmds": startupCmds_reformatted, "startup-cmds-delay": startupDelay, "users-filename": usersFilename }) logging.debug( "getExperimentVMRolledOut(): finished setting up clone: " + str(vmRolledOutList)) self.rolledoutjson[configname] = vmRolledOutList, numClones return vmRolledOutList, numClones except Exception: logging.error( "Error in getExperimentVMRolledOut(): An error occured. Check that file exists and that it is properly formatted." ) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None def getValidVMsFromTypeName(self, configname, itype, name, rolledoutjson=None): logging.debug("getValidVMsFromTypeName(): instantiated") if rolledoutjson == None: rolledoutjson = self.getExperimentVMRolledOut(configname) #get VMs or sets that we need to start validvms = [] validvmnames = [] if name == "all": #if none was specified, just add all vms to the list validvms = self.getExperimentVMListsFromRolledOut( configname, rolledoutjson) for vm in validvms: validvmnames.append(vm["name"]) elif itype == "set": validvms = self.getExperimentVMsInSetFromRolledOut( configname, name, rolledoutjson) for vm in validvms: validvmnames.append(vm) elif itype == "template": validvms = [] if name in self.getExperimentVMNamesFromTemplateFromRolledOut( configname, rolledoutjson): validvms = self.getExperimentVMNamesFromTemplateFromRolledOut( configname, rolledoutjson)[name] for vm in validvms: validvmnames.append(vm) elif itype == "vm": validvmnames.append(name) elif itype == "": #if none was specified, just add all vms to the list validvms = self.getExperimentVMListsFromRolledOut( configname, rolledoutjson) for vm in validvms: validvmnames.append(vm["name"]) return validvmnames def getExperimentVMsInSetFromRolledOut(self, configname, set_num, rolledout_jsondata=None): logging.debug( "ExperimentConfigIO: getExperimentVMsInSetFromRolledOut(): instantiated" ) sets = self.getExperimentSetDictFromRolledOut( configname, rolledout_jsondata=rolledout_jsondata) set_num_str = str(set_num) if set_num_str not in sets: return [] return sets[set_num_str] def getExperimentSetDictFromRolledOut(self, configname, rolledout_jsondata=None): logging.debug( "ExperimentConfigIO: getExperimentSetListsFromJSON(): instantiated" ) if rolledout_jsondata == None: logging.debug( "ExperimentConfigIO: no json provided, reading from file") rolledout_jsondata = self.getExperimentVMRolledOut( self, configname) (template_vms, num_clones) = rolledout_jsondata sets = {} for template_vm in template_vms: for clone_num in range(num_clones): if str(clone_num + 1) not in sets: sets[str(clone_num + 1)] = [] sets[str(clone_num + 1)].append( template_vms[template_vm][clone_num]["name"]) return sets def getExperimentVMNamesFromTemplateFromRolledOut(self, configname, rolledout_jsondata=None): logging.debug( "ExperimentConfigIO: getExperimentVMNamesFromTemplateFromRolledOut(): instantiated" ) if rolledout_jsondata == None: logging.debug( "getExperimentVMNamesFromTemplateFromRolledOut(): no json provided, reading from file" ) rolledout_jsondata = self.getExperimentVMRolledOut( self, configname) (template_vms, num_clones) = rolledout_jsondata templates = {} for template_vm in template_vms: if template_vm not in templates: templates[template_vm] = [] for vminfo in template_vms[template_vm]: vmname = vminfo["name"] templates[template_vm].append(vmname) return templates def getExperimentVMListsFromRolledOut(self, configname, rolledout_jsondata=None): logging.debug( "ExperimentConfigIO: getExperimentVMListsFromRolledOut(): instantiated" ) if rolledout_jsondata == None: logging.debug( "getExperimentVMListsFromRolledOut(): no json provided, reading from file" ) rolledout_jsondata = self.getExperimentVMRolledOut( self, configname) (template_vms, num_clones) = rolledout_jsondata vms = [] for template_vm in template_vms: for cloned_vm in template_vms[template_vm]: vms.append(cloned_vm) return vms def getExperimentJSONFileData(self, configname, force_refresh=False): logging.debug( "ExperimentConfigIO: getExperimentJSONFileData(): instantiated") if configname in self.config_jsondata: if force_refresh == False: return self.config_jsondata[configname] try: jsonconfigfile = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], configname, "Experiments", configname + ".json") with open(jsonconfigfile) as fd: jsondata = json.load(fd) self.config_jsondata[configname] = jsondata return jsondata except FileNotFoundError: logging.error("getExperimentJSONFileData(): File not found: " + str(jsonconfigfile)) return None except Exception: logging.error( "Error in getExperimentJSONFileData(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None def writeExperimentXMLFileData(self, jsondata, configname): logging.debug( "ExperimentConfigIO: writeExperimentXMLFileData(): instantiated") try: xmlconfigfile = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], configname, "Experiments", configname + ".xml") with open(xmlconfigfile, 'w') as fd: xmltodict.unparse(jsondata, output=fd, pretty=True) except Exception: logging.error( "Error in writeExperimentXMLFileData(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None def writeExperimentJSONFileData(self, jsondata, configname): logging.debug( "ExperimentConfigIO: writeExperimentJSONFileData(): instantiated") try: jsonconfigfile = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], configname, "Experiments", configname + ".json") with open(jsonconfigfile, 'w') as fd: json.dump(jsondata, fd, indent=4) except Exception: logging.error( "Error in writeExperimentJSONFileData(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None def getExperimentXMLFilenames(self, pathcontains=""): logging.debug( "ExperimentConfigIO: getExperimentXMLFilenames(): Instantiated") try: #First get the folds in the experiments directory as specified in the config file xmlExperimentFilenames = [] xmlExperimentNames = [] experimentpath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH']) name_list = os.listdir(experimentpath) dirs = [] for name in name_list: fullpath = os.path.join(experimentpath, name) if os.path.isdir(fullpath) and (pathcontains in name): dirs.append(fullpath) logging.debug("getExperimentXMLFilenames(): Completed " + str(dirs)) if dirs == None or dirs == []: return [xmlExperimentFilenames, xmlExperimentNames] #now get the actual xml experiment files xmlExperimentFilenames = [] xmlExperimentNames = [] for basepath in dirs: #basepath e.g., ExperimentData/sample xmlExperimentPath = os.path.join(basepath, "Experiments") #xmlExperimentPath e.g., ExperimentData/sample/Experiments logging.debug("getExperimentXMLFilenames(): looking at dir " + str(xmlExperimentPath)) if os.path.exists(xmlExperimentPath): xmlNameList = os.listdir(xmlExperimentPath) logging.debug( "getExperimentXMLFilenames(): looking at files " + str(xmlNameList)) #xmlNameList e.g., [sample.xml] for name in xmlNameList: fullpath = os.path.join(xmlExperimentPath, name) logging.debug( "getExperimentXMLFilenames(): looking at fullpath " + str(fullpath)) if fullpath.endswith(".xml"): xmlExperimentFilenames.append(fullpath) baseNoExt = os.path.basename(name) baseNoExt = os.path.splitext(baseNoExt)[0] xmlExperimentNames.append(baseNoExt) logging.debug( "getExperimentXMLFilenames(): adding " + str(xmlExperimentFilenames) + " " + str(xmlExperimentNames)) return [xmlExperimentFilenames, xmlExperimentNames] except FileNotFoundError: logging.error( "Error in getExperimentXMLFilenames(): Path not found: " + str(experimentpath)) return None except Exception: logging.error( "Error in getExperimentXMLFilenames(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None
class MainApp(QWidget): def __init__(self, parent=None): logging.debug("MainApp:init() instantiated") super().__init__() self.baseWidgets = {} self.vmWidgets = {} self.materialWidgets = {} self.cf = SystemConfigIO() self.ec = ExperimentConfigIO.getInstance() self.statusBar = QStatusBar() self.setMinimumSize(670, 565) quit = QAction("Quit", self) quit.triggered.connect(self.closeEvent) self.setWindowTitle("ARL South RES v0.1") self.tabWidget = QtWidgets.QTabWidget() self.tabWidget.setGeometry(QtCore.QRect(0, 15, 668, 565)) self.tabWidget.setObjectName("tabWidget") # Configuration Window (windowBox) contains: ## windowBoxHLayout contains: ###experimentTree (Left) ###basedataStackedWidget (Right) self.windowWidget = QtWidgets.QWidget() self.windowWidget.setObjectName("windowWidget") self.windowBoxHLayout = QtWidgets.QHBoxLayout() #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0) self.windowBoxHLayout.setObjectName("windowBoxHLayout") self.windowWidget.setLayout(self.windowBoxHLayout) self.experimentTree = QtWidgets.QTreeWidget() self.experimentTree.itemSelectionChanged.connect(self.onItemSelected) self.experimentTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.experimentTree.customContextMenuRequested.connect( self.showContextMenu) self.experimentTree.setEnabled(True) self.experimentTree.setMinimumSize(200, 521) self.experimentTree.setMaximumWidth(350) self.experimentTree.setObjectName("experimentTree") self.experimentTree.headerItem().setText(0, "Experiments") self.experimentTree.setSortingEnabled(False) self.windowBoxHLayout.addWidget(self.experimentTree) self.basedataStackedWidget = QStackedWidget() self.basedataStackedWidget.setObjectName("basedataStackedWidget") self.basedataStackedWidget.setEnabled(False) self.windowBoxHLayout.addWidget(self.basedataStackedWidget) self.tabWidget.addTab(self.windowWidget, "Configuration") # VBox Actions Tab self.experimentActionsWidget = ExperimentActionsWidget( statusBar=self.statusBar) self.experimentActionsWidget.setObjectName("experimentActionsWidget") self.tabWidget.addTab(self.experimentActionsWidget, "Experiment Actions") # Remote Connections Tab self.connectionWidget = ConnectionWidget(statusBar=self.statusBar) self.connectionWidget.setObjectName("connectionsWidget") self.tabWidget.addTab(self.connectionWidget, "Remote Connections") #Create the bottom layout so that we can access the status bar self.bottomLayout = QHBoxLayout() self.statusBar.showMessage("Loading GUI...") self.bottomLayout.addWidget(self.statusBar) self.saveButton = QtWidgets.QPushButton("Save Current") self.saveButton.clicked.connect(self.saveExperimentButton) self.saveButton.setEnabled(False) self.bottomLayout.addWidget(self.saveButton) self.populateUi() self.setupContextMenus() self.initMenu() self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.mainMenu) self.mainLayout.addWidget(self.tabWidget) self.mainLayout.addLayout(self.bottomLayout) self.setLayout(self.mainLayout) #self.setCentralWidget(self.outerBox) self.tabWidget.setCurrentIndex(0) #self.statusBar.showMessage("Finished Loading GUI Components") # Plugin Section self.tabWidget.addTab(CTFi2GUI(), "CTFi2") def readSystemConfig(self): logging.debug("MainApp:readSystemConfig() instantiated") self.vboxPath = self.cf.getConfig()['VBOX']['VMANAGE_PATH'] self.experimentPath = self.cf.getConfig( )['EXPERIMENTS']['EXPERIMENTS_PATH'] self.statusBar.showMessage("Finished reading system config") def setupContextMenus(self): logging.debug("MainApp:setupContextMenus() instantiated") # Context menu for blank space self.blankTreeContextMenu = QtWidgets.QMenu() self.addExperiment = self.blankTreeContextMenu.addAction( "New Experiment") self.addExperiment.triggered.connect(self.addExperimentActionEvent) self.importExperiment = self.blankTreeContextMenu.addAction( "Import Experiment from RES archive") self.importExperiment.triggered.connect(self.importActionEvent) # Experiment context menu self.experimentContextMenu = QtWidgets.QMenu() self.addVMContextSubMenu = QtWidgets.QMenu() self.experimentContextMenu.addMenu(self.addVMContextSubMenu) self.addVMContextSubMenu.setTitle("Add") self.addVM = self.addVMContextSubMenu.addAction("Virtual Machines") self.addVM.triggered.connect(self.addVMActionEvent) self.addMaterial = self.addVMContextSubMenu.addAction("Material Files") self.addMaterial.triggered.connect(self.addMaterialActionEvent) # Add line separator here self.removeExperiment = self.experimentContextMenu.addAction( "Remove Experiment") self.removeExperiment.triggered.connect( self.removeExperimentItemActionEvent) self.exportExperiment = self.experimentContextMenu.addAction( "Export Experiment") self.exportExperiment.triggered.connect(self.exportActionEvent) # VM/Material context menu self.itemContextMenu = QtWidgets.QMenu() self.removeItem = self.itemContextMenu.addAction( "Remove Experiment Item") self.removeItem.triggered.connect(self.removeExperimentItemActionEvent) def populateUi(self): logging.debug("MainApp:populateUi() instantiated") self.statusBar.showMessage("Populating UI") self.readSystemConfig() #####Create the following based on the config file result = self.ec.getExperimentXMLFilenames() if result == None: return [xmlExperimentFilenames, xmlExperimentNames] = result if xmlExperimentFilenames == [] or xmlExperimentNames == []: self.statusBar.showMessage("No configs found") return #For all experiment files found for configname in xmlExperimentNames: ####Read Experiment Config Data and Populate Tree self.loadConfigname(configname) self.statusBar.showMessage( "Completed populating the User Interface from " + str(len(xmlExperimentNames)) + " config files read", 6000) ############################### def loadConfigname(self, configname): logging.debug("MainApp(): loadConfigname instantiated") logging.info("Reading XML data for " + str(configname)) jsondata = self.ec.getExperimentXMLFileData(configname) self.statusBar.showMessage("Finished reading experiment config") ##########testbed-setup data###### if jsondata == None: jsondata = {} if "xml" not in jsondata or jsondata["xml"] == None or str( jsondata["xml"]).strip() == "": jsondata["xml"] = {} if "testbed-setup" not in jsondata["xml"]: jsondata["xml"]["testbed-setup"] = {} if "vm-set" not in jsondata["xml"]["testbed-setup"]: jsondata["xml"]["testbed-setup"]["vm-set"] = {} #Temporary fix for older xml/json files. if "users-filename" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["users-filename"] = "" if "rdp-broker-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["rdp-broker-ip"] = "" if "chat-server-ip" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["chat-server-ip"] = "" configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree) configTreeWidgetItem.setText(0, configname) self.experimentActionsWidget.addExperimentItem( configname, config_jsondata=jsondata) self.connectionWidget.addExperimentItem(configname, config_jsondata=jsondata) basejsondata = jsondata["xml"] # Base Config Widget self.baseWidget = BaseWidget(self, configname, configname, basejsondata) self.baseWidgets[configname] = { "BaseWidget": {}, "VMWidgets": {}, "MaterialWidgets": {} } self.baseWidgets[configname]["BaseWidget"] = self.baseWidget self.basedataStackedWidget.addWidget(self.baseWidget) ##########vm data###### if "vm" in jsondata["xml"]["testbed-setup"]["vm-set"]: vmsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"]["vm"] if isinstance(vmsjsondata, list): for vm in vmsjsondata: vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) vmlabel = "V: " + vm["name"] vm_item.setText(0, vmlabel) # VM Config Widget vmWidget = VMWidget(None, configname, vm["name"], vm) self.baseWidgets[configname]["VMWidgets"][ vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) else: vm_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) vmlabel = "V: " + vmsjsondata["name"] vm_item.setText(0, vmlabel) # VM Config Widget vmWidget = VMWidget(None, configname, vmsjsondata["name"], vmsjsondata) self.baseWidgets[configname]["VMWidgets"][vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) ##########material data###### if "material" in jsondata["xml"]["testbed-setup"]["vm-set"]: materialsjsondata = jsondata["xml"]["testbed-setup"]["vm-set"][ "material"] if isinstance(materialsjsondata, list): for material in materialsjsondata: material_item = QtWidgets.QTreeWidgetItem( configTreeWidgetItem) materiallabel = "M: " + material["name"] material_item.setText(0, materiallabel) # Material Config Widget materialWidget = MaterialWidget(None, configname, material["name"], material) self.baseWidgets[configname]["MaterialWidgets"][ materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) else: material_item = QtWidgets.QTreeWidgetItem(configTreeWidgetItem) materiallabel = "M: " + materialsjsondata["name"] material_item.setText(0, materiallabel) # Material Config Widget materialWidget = MaterialWidget(None, configname, materialsjsondata["name"], materialsjsondata) self.baseWidgets[configname]["MaterialWidgets"][ materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) logging.debug("MainApp(): Finished loading configname: " + str(configname)) def onItemSelected(self): logging.debug("MainApp:onItemSelected instantiated") # Get the selected item selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "No configuration items selected or available.") return self.basedataStackedWidget.setEnabled(True) # Now enable the save button self.saveButton.setEnabled(True) self.saveExperimentMenuButton.setEnabled(True) #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if (parentSelectedItem == None): #A base widget was selected self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[selectedItem.text(0)]["BaseWidget"]) else: #Check if it's the case that a VM Name was selected if (selectedItem.text(0)[0] == "V"): logging.debug("Setting right widget: " + str(self.baseWidgets[parentSelectedItem.text(0)] ["VMWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[parentSelectedItem.text(0)]["VMWidgets"][ selectedItem.text(0)]) #Check if it's the case that a Material Name was selected elif (selectedItem.text(0)[0] == "M"): logging.debug("Setting right widget: " + str(self.baseWidgets[parentSelectedItem.text(0)] ["MaterialWidgets"][selectedItem.text(0)])) self.basedataStackedWidget.setCurrentWidget( self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)]) def showContextMenu(self, position): logging.debug("MainApp:showContextMenu() instantiated: " + str(position)) if (self.experimentTree.itemAt(position) == None): self.blankTreeContextMenu.popup( self.experimentTree.mapToGlobal(position)) elif (self.experimentTree.itemAt(position).parent() == None): self.experimentContextMenu.popup( self.experimentTree.mapToGlobal(position)) else: self.itemContextMenu.popup( self.experimentTree.mapToGlobal(position)) def addExperimentActionEvent(self): logging.debug("MainApp:addExperimentActionEvent() instantiated") configname = ExperimentAddDialog().experimentAddDialog( self, self.baseWidgets.keys()) if configname != None: logging.debug( "configureVM(): OK pressed and valid configname entered: " + str(configname)) else: logging.debug("configureVM(): Cancel pressed or no VM selected") return ##Now add the item to the tree widget and create the baseWidget configTreeWidgetItem = QtWidgets.QTreeWidgetItem(self.experimentTree) configTreeWidgetItem.setText(0, configname) self.experimentActionsWidget.addExperimentItem(configname) self.connectionWidget.addExperimentItem(configname) # Base Config Widget self.baseWidget = BaseWidget(self, configname, configname) self.baseWidgets[configname] = { "BaseWidget": {}, "VMWidgets": {}, "MaterialWidgets": {} } self.baseWidgets[configname]["BaseWidget"] = self.baseWidget self.basedataStackedWidget.addWidget(self.baseWidget) self.statusBar.showMessage("Added new experiment: " + str(configname)) def importActionEvent(self): logging.debug("MainApp:importActionEvent() instantiated") #Check if it's the case that an experiment name was selected confignamesChosen = PackageImportDialog().packageImportDialog( self, self.baseWidgets.keys()) if confignamesChosen == []: logging.debug( "importActionEvent(): Canceled or a file could not be imported. make sure file exists." ) return #for fileChosen in filesChosen: logging.debug( "MainApp: importActionEvent(): Files choosen (getting only first): " + confignamesChosen) firstConfignameChosen = confignamesChosen self.loadConfigname(firstConfignameChosen) #Add the items to the tree self.statusBar.showMessage("Imported " + firstConfignameChosen) def addVMActionEvent(self): logging.debug("MainApp:addVMActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:addVMActionEvent no configurations left") self.statusBar.showMessage( "Could not add VM. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Now allow the user to choose the VM: (response, vmsChosen) = VMRetrieveDialog(self).exec_() if response == QMessageBox.Ok and vmsChosen != None: logging.debug("configureVM(): OK pressed and VMs selected " + str(vmsChosen)) else: logging.debug("configureVM(): Cancel pressed or no VM selected") return if vmsChosen == []: logging.debug( "configureVM(): Canceled or a file could not be added. Try again later or check permissions" ) return for vmChosen in vmsChosen: logging.debug("MainApp: addVMActionEvent(): File choosen: " + str(vmChosen)) #Add the item to the tree vmItem = QtWidgets.QTreeWidgetItem(selectedItem) vmlabel = "V: " + vmChosen vmItem.setText(0, vmlabel) # VM Config Widget #Now add the item to the stack and list of baseWidgets vmjsondata = {"name": vmChosen} vmWidget = VMWidget(self, selectedItemName, vmChosen, vmjsondata) self.baseWidgets[selectedItemName]["VMWidgets"][vmlabel] = vmWidget self.basedataStackedWidget.addWidget(vmWidget) #Now add data to the experimentActionWidget associated with the current config #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if parentSelectedItem != None: selectedItem = parentSelectedItem configname = selectedItem.text(0) config_jsondata = self.getWritableData(configname) self.experimentActionsWidget.resetExperiment( configname, config_jsondata=config_jsondata) self.connectionWidget.resetExperiment(configname, config_jsondata=config_jsondata) self.statusBar.showMessage("Added " + str(len(vmsChosen)) + " VM files to experiment: " + str(selectedItemName)) def startHypervisorActionEvent(self): logging.debug("MainApp:startHypervisorActionEvent() instantiated") logging.debug( "MainApp:startHypervisorActionEvent no configurations left") # Try to open the hypervisor and check if it worked or not result = HypervisorOpenDialog().hypervisorOpenDialog(self) if result != "success": logging.debug( "startHypervisorActionEvent(): Could not start the hypervisor") self.statusBar.showMessage("Hypervisor could not be started.") return self.statusBar.showMessage("Started hypervisor.") def addMaterialActionEvent(self): logging.debug("MainApp:addMaterialActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug( "MainApp:addMaterialActionEvent no configurations left") self.statusBar.showMessage( "Could not add item. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Check if it's the case that an experiment name was selected filesChosen = MaterialAddFileDialog().materialAddFileDialog( selectedItemName) if filesChosen == []: logging.debug( "addMaterialActionEvent(): Canceled or a file could not be added. Try again later or check permissions" ) return for fileChosen in filesChosen: fileChosen = os.path.basename(fileChosen) logging.debug("MainApp: addMaterialActionEvent(): File choosen: " + fileChosen) #Add the item to the tree material_item = QtWidgets.QTreeWidgetItem(selectedItem) materiallabel = "M: " + fileChosen material_item.setText(0, materiallabel) # Material Config Widget #Now add the item to the stack and list of baseWidgets materialsjsondata = {"name": fileChosen} materialWidget = MaterialWidget(self, selectedItemName, fileChosen, materialsjsondata) self.baseWidgets[selectedItem.text( 0)]["MaterialWidgets"][materiallabel] = materialWidget self.basedataStackedWidget.addWidget(materialWidget) self.statusBar.showMessage("Added " + str(len(filesChosen)) + " material files to experiment: " + str(selectedItemName)) def removeExperimentItemActionEvent(self): logging.debug("MainApp:removeExperimentItemActionEvent() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "Could not remove. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if (parentSelectedItem == None): #A base widget was selected successfilenames = ExperimentRemoveFileDialog( ).experimentRemoveFileDialog(selectedItemName) if successfilenames == [] or successfilenames == "": logging.debug( "removeExperimentItemActionEvent(): Canceled or a file could not be removed. Try again later or check permissions" ) return self.experimentTree.invisibleRootItem().removeChild(selectedItem) self.basedataStackedWidget.removeWidget( self.baseWidgets[selectedItemName]["BaseWidget"]) del self.baseWidgets[selectedItemName] self.experimentActionsWidget.removeExperimentItem(selectedItemName) self.experimentActionsWidget.removeExperimentItem(selectedItemName) self.statusBar.showMessage("Removed experiment: " + str(selectedItemName)) else: #Check if it's the case that a VM Name was selected if (selectedItem.text(0)[0] == "V"): parentSelectedItem.removeChild(selectedItem) configname = parentSelectedItem.text(0) self.basedataStackedWidget.removeWidget( self.baseWidgets[configname]["VMWidgets"][ selectedItem.text(0)]) del self.baseWidgets[configname]["VMWidgets"][ selectedItem.text(0)] self.statusBar.showMessage("Removed VM: " + str(selectedItemName) + " from experiment: " + str(parentSelectedItem.text(0))) #Also remove from the experiment action widget: config_jsondata = self.getWritableData(configname) self.experimentActionsWidget.resetExperiment( configname, config_jsondata=config_jsondata) self.connectionWidget.resetExperiment( configname, config_jsondata=config_jsondata) #Check if it's the case that a Material Name was selected elif (selectedItem.text(0)[0] == "M"): materialName = selectedItemName.split("M: ")[1] successfilenames = MaterialRemoveFileDialog( ).materialRemoveFileDialog(parentSelectedItem.text(0), materialName) if successfilenames == []: logging.debug( "Canceled or a file could not be removed. Try again later or check permissions" ) return parentSelectedItem.removeChild(selectedItem) self.basedataStackedWidget.removeWidget( self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)]) del self.baseWidgets[parentSelectedItem.text( 0)]["MaterialWidgets"][selectedItem.text(0)] self.statusBar.showMessage("Removed Material: " + str(materialName) + " from experiment: " + str(parentSelectedItem.text(0))) def exportActionEvent(self): logging.debug("MainApp:exportActionEvent() instantiated") #Check if it's the case that an experiment name was selected selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:exportActionEvent no configurations left") self.statusBar.showMessage( "Could not export experiment. No configuration items selected or available." ) return selectedItemName = selectedItem.text(0) folderChosen = PackageExportDialog().packageExportDialog( self, selectedItemName) if folderChosen == []: logging.debug( "exportActionEvent(): Canceled or the experiment could not be exported. Check folder permissions." ) return folderChosen = os.path.basename(folderChosen[0]) logging.debug("MainApp: exportActionEvent(): File choosen: " + folderChosen) #Add the items to the tree self.statusBar.showMessage("Exported to " + folderChosen) def editPathActionEvent(self): logging.debug("MainApp:editPathActionEvent() instantiated") result = ConfigurationDialog(self).exec_() def closeEvent(self, event): logging.debug("MainApp:closeEvent(): instantiated") logging.debug("closeEvent(): returning accept") event.accept() qApp.quit() return def initMenu(self): self.mainMenu = QMenuBar() self.fileMenu = self.mainMenu.addMenu("File") self.editMenu = self.mainMenu.addMenu("Edit") self.hypervisorMenu = self.mainMenu.addMenu("Hypervisor") self.newExperimentMenuButton = QAction(QIcon(), "New Experiment", self) self.newExperimentMenuButton.setShortcut("Ctrl+N") self.newExperimentMenuButton.setStatusTip("Create New Experiment") self.newExperimentMenuButton.triggered.connect( self.addExperimentActionEvent) self.fileMenu.addAction(self.newExperimentMenuButton) self.importExperimentMenuButton = QAction(QIcon(), "Import Experiment", self) self.importExperimentMenuButton.setShortcut("Ctrl+I") self.importExperimentMenuButton.setStatusTip( "Import Experiment from RES File") self.importExperimentMenuButton.triggered.connect( self.importActionEvent) self.fileMenu.addAction(self.importExperimentMenuButton) self.saveExperimentMenuButton = QAction(QIcon(), "Save Experiment", self) self.saveExperimentMenuButton.setShortcut("Ctrl+I") self.saveExperimentMenuButton.setStatusTip( "Save currently selected experiment") self.saveExperimentMenuButton.triggered.connect( self.saveExperimentButton) self.saveExperimentMenuButton.setEnabled(False) self.fileMenu.addAction(self.saveExperimentMenuButton) self.exitMenuButton = QAction(QIcon("exit24.png"), "Exit", self) self.exitMenuButton.setShortcut("Ctrl+Q") self.exitMenuButton.setStatusTip("Exit application") self.exitMenuButton.triggered.connect(self.close) self.fileMenu.addAction(self.exitMenuButton) self.pathMenuButton = QAction(QIcon(), "Edit Paths", self) self.pathMenuButton.setShortcut("Ctrl+E") self.pathMenuButton.setStatusTip("Edit Paths") self.pathMenuButton.triggered.connect(self.editPathActionEvent) self.editMenu.addAction(self.pathMenuButton) self.startHypervisorMenuButton = QAction(QIcon(), "Instantiate Hypervisor", self) self.startHypervisorMenuButton.setShortcut("Ctrl+O") self.startHypervisorMenuButton.setStatusTip( "Start the hypervisor that is currently configured") self.startHypervisorMenuButton.triggered.connect( self.startHypervisorActionEvent) self.hypervisorMenu.addAction(self.startHypervisorMenuButton) def getWritableData(self, configname): logging.debug("MainApp: getWritableData() instantiated") jsondata = {} jsondata["xml"] = {} #get baseWidget data baseWidget = self.baseWidgets[configname]["BaseWidget"] ###TODO: make this work for multiple experiments (current testing assumes only one) if isinstance(baseWidget, BaseWidget): jsondata["xml"] = baseWidget.getWritableData() ###Setup the dictionary if "testbed-setup" not in jsondata["xml"]: jsondata["xml"]["testbed-setup"] = {} if "vm-set" not in jsondata["xml"]["testbed-setup"]: jsondata["xml"]["testbed-setup"]["vm-set"] = {} if "vm" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["vm"] = [] if "material" not in jsondata["xml"]["testbed-setup"]["vm-set"]: jsondata["xml"]["testbed-setup"]["vm-set"]["material"] = [] for vmData in self.baseWidgets[configname]["VMWidgets"].values(): jsondata["xml"]["testbed-setup"]["vm-set"]["vm"].append( vmData.getWritableData()) for materialData in self.baseWidgets[configname][ "MaterialWidgets"].values(): jsondata["xml"]["testbed-setup"]["vm-set"]["material"].append( materialData.getWritableData()) return jsondata def saveExperimentButton(self): logging.debug("MainApp: saveExperiment() instantiated") self.saveExperiment() def saveExperiment(self, configname=None): logging.debug("MainApp: saveExperiment() instantiated") selectedItem = self.experimentTree.currentItem() if selectedItem == None: logging.debug("MainApp:onItemSelected no configurations left") self.statusBar.showMessage( "Could not save. No configuration items selected or available." ) return #Check if it's the case that an experiment name was selected parentSelectedItem = selectedItem.parent() if parentSelectedItem != None: selectedItem = parentSelectedItem configname = selectedItem.text(0) jsondata = self.getWritableData(configname) self.ec.writeExperimentXMLFileData(jsondata, configname) self.ec.writeExperimentJSONFileData(jsondata, configname) self.ec.getExperimentVMRolledOut(configname, jsondata, force_refresh=True) res = self.ec.getExperimentServerInfo(configname) #Now reset the experimentActions view self.experimentActionsWidget.resetExperiment(configname, jsondata) self.connectionWidget.resetExperiment(configname, jsondata) self.statusBar.showMessage( "Succesfully saved experiment file for " + str(configname), 2000)
class VBoxManage(VMManage): def __init__(self, initializeVMManage=True): logging.info("VBoxManage.__init__(): instantiated") VMManage.__init__(self) self.cf = SystemConfigIO() self.vmanage_path = self.cf.getConfig()['VBOX']['VMANAGE_PATH'] # A lock for acces/updates to self.vms self.lock = RLock() self.vms = {} self.tempVMs = {} if initializeVMManage: self.refreshAllVMInfo() result = self.getManagerStatus()["writeStatus"] while result != self.MANAGER_IDLE: #waiting for manager to finish query... result = self.getManagerStatus()["writeStatus"] time.sleep(.1) def configureVMNet(self, vmName, netNum, netName): logging.info("VBoxManage: configureVMNet(): instantiated") #check to make sure the vm is known, if not should refresh or check name: exists = False try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("configureVMNet(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runConfigureVMNet, args=(vmName, netNum, netName)) t.start() return 0 finally: self.lock.release() def configureVMNets(self, vmName, internalNets): logging.info("VBoxManageWin: configureVMNets(): instantiated") #check to make sure the vm is known, if not should refresh or check name: exists = False try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("configureVMNets(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runConfigureVMNets, args=(vmName, internalNets)) t.start() return 0 finally: self.lock.release() def runConfigureVMNets(self, vmName, internalNets): try: logging.debug("VBoxManage: runConfigureVMNets(): instantiated") self.readStatus = VMManage.MANAGER_READING logging.debug("runConfigureVMNets(): adding 1 " + str(self.writeStatus)) cloneNetNum = 1 logging.debug( "runConfigureVMNets(): Processing internal net names: " + str(internalNets)) vmUUID = "" try: self.lock.acquire() vmUUID = str(self.vms[vmName].UUID) finally: self.lock.release() for internalnet in internalNets: vmConfigVMCmd = self.vmanage_path + " modifyvm " + vmUUID + " --nic" + str( cloneNetNum) + " intnet " + " --intnet" + str( cloneNetNum) + " " + str( internalnet) + " --cableconnected" + str( cloneNetNum) + " on " logging.debug("runConfigureVMNets(): Running " + vmConfigVMCmd) subprocess.check_output(shlex.split(vmConfigVMCmd, posix=self.POSIX), encoding='utf-8') cloneNetNum += 1 logging.debug("runConfigureVMNets(): Thread completed") except Exception: logging.error("runConfigureVMNets() Error: " + " cmd: " + vmConfigVMCmd) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runConfigureVMNets(): sub 1 " + str(self.writeStatus)) def guestCommands(self, vmName, cmds, delay=0): logging.debug("VBoxManageWin: guestCommands(): instantiated") #check to make sure the vm is known, if not should refresh or check name: exists = False try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("guestCommands(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 self.guestThreadStatus += 1 t = threading.Thread(target=self.runGuestCommands, args=(vmName, cmds, delay)) t.start() return 0 finally: self.lock.release() def runGuestCommands(self, vmName, cmds, delay): try: logging.debug("runGuestCommands(): adding 1 " + str(self.writeStatus)) cmd = "N/A" #if a delay was specified... wait time.sleep(int(delay)) for cmd in cmds: vmCmd = self.vmanage_path + " guestcontrol " + str( self.vms[vmName].UUID) + " " + cmd logging.debug("runGuestCommands(): Running " + vmCmd) p = Popen(shlex.split(vmCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': logging.debug("output line: " + out) p.wait() logging.debug("runGuestCommands(): Thread completed") except Exception: logging.error("runGuestCommands() Error: " + " cmd: " + cmd) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.guestThreadStatus -= 1 logging.debug("runGuestCommands(): sub thread 1 " + str(self.writeStatus)) def refreshAllVMInfo(self): logging.info("VBoxManage: refreshAllVMInfo(): instantiated") logging.debug("getListVMS() Starting List VMs thread") self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMSInfo) t.start() def refreshVMInfo(self, vmName): logging.info("VBoxManage: refreshVMInfo(): instantiated: " + str(vmName)) logging.debug("refreshVMInfo() refresh VMs thread") #check to make sure the vm is known, if not should refresh or check name: exists = False try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("refreshVMInfo(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMInfo, args=(vmName, )) t.start() return 0 finally: self.lock.release() def runVMSInfo(self): logging.debug("VBoxManageWin: runVMSInfo(): instantiated") try: vmListCmd = self.vmanage_path + " list vms" logging.debug("runVMSInfo(): Collecting VM Names using cmd: " + vmListCmd) #clear out the current set self.tempVMs = {} self.readStatus = VMManage.MANAGER_READING logging.debug("runVMSInfo(): adding 1 " + str(self.writeStatus)) p = Popen(shlex.split(vmListCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': splitOut = out.split("{") vm = VM() tmpname = splitOut[0].strip() #has to be at least one character and every name has a start and end quote if len(tmpname) > 2: vm.name = splitOut[0].strip()[1:-1] else: break vm.UUID = splitOut[1].split("}")[0].strip() # logging.debug("UUID: " + vm.UUID) self.tempVMs[vm.name] = vm p.wait() logging.debug("runVMSInfo(): Thread 1 completed: " + vmListCmd) logging.debug("runVMSInfo(): Found # VMS: " + str(len(self.tempVMs))) #for each vm, get the machine readable info logging.debug("runVMSInfo(): collecting VM extended info") vmNum = 1 vmShowInfoCmd = "" for aVM in self.tempVMs: logging.debug("runVMSInfo(): collecting # " + str(vmNum) + " of " + str(len(self.tempVMs)) + " : " + str(aVM)) vmShowInfoCmd = self.vmanage_path + " showvminfo " + str( self.tempVMs[aVM].UUID) + " --machinereadable" logging.debug("runVMSInfo(): Running " + vmShowInfoCmd) p = Popen(shlex.split(vmShowInfoCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': #match example: nic1="none" res = re.match("nic[0-9]+=", out) if res: # logging.debug("Found nic: " + out + " added to " + self.tempVMs[aVM].name) out = out.strip() nicNum = out.split("=")[0][3:] nicType = out.split("=")[1] self.tempVMs[aVM].adaptorInfo[nicNum] = nicType res = re.match("groups=", out) if res: # logging.debug("Found groups: " + out + " added to " + self.tempVMs[aVM].name) self.tempVMs[aVM].groups = out.strip() res = re.match("VMState=", out) if res: # logging.debug("Found vmState: " + out + " added to " + self.tempVMs[aVM].name) state = out.strip().split("\"")[1].split("\"")[0] self.tempVMs[aVM].state = state res = re.match("CurrentSnapshotUUID=", out) if res: # logging.debug("Found snaps: " + out + " added to " + self.tempVMs[aVM].latestSnapUUID) latestSnap = out.strip().split("\"")[1].split( "\"")[0] self.tempVMs[aVM].latestSnapUUID = latestSnap p.wait() vmNum = vmNum + 1 try: self.lock.acquire() self.vms = self.tempVMs finally: self.lock.release() logging.debug("runVMSInfo(): Thread 2 completed: " + vmShowInfoCmd) except Exception: logging.error("Error in runVMSInfo(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runVMSInfo(): sub 1 " + str(self.writeStatus)) def runVMInfo(self, vmName): logging.debug("VBoxManage: runVMInfo(): instantiated") try: #run vboxmanage to get vm listing #Make sure this one isn't cleared before use too... vmListCmd = self.vmanage_path + " list vms" logging.debug("runVMInfo(): Collecting VM Names using cmd: " + vmListCmd) self.readStatus = VMManage.MANAGER_READING logging.debug("runVMInfo(): adding 1 " + str(self.writeStatus)) p = Popen(shlex.split(vmListCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': splitOut = out.split("{") vm = VM() tmpname = splitOut[0].strip() #has to be at least one character and every name has a start and end quote if len(tmpname) > 2: vm.name = splitOut[0].strip()[1:-1] else: break vm.UUID = splitOut[1].split("}")[0].strip() # logging.debug("UUID: " + vm.UUID) self.tempVMs[vm.name] = vm p.wait() logging.debug("runVMInfo(): Thread 1 completed: " + vmListCmd) logging.debug("runVMInfo(): Found # VMS: " + str(len(self.tempVMs))) if vmName not in self.tempVMs: logging.error("runVMInfo(): VM was not found/registered: " + vmName) return #get the machine readable info logging.debug("runVMInfo(): collecting VM extended info") vmShowInfoCmd = "" vmShowInfoCmd = self.vmanage_path + " showvminfo " + str( self.tempVMs[vmName].UUID) + " --machinereadable" logging.debug("runVMInfo(): Running " + vmShowInfoCmd) p = Popen(shlex.split(vmShowInfoCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': #match example: nic1="none" res = re.match("nic[0-9]+=", out) if res: out = out.strip() nicNum = out.split("=")[0][3:] nicType = out.split("=")[1] self.tempVMs[vmName].adaptorInfo[nicNum] = nicType res = re.match("groups=", out) if res: # logging.debug("Found groups: " + out + " added to " + self.tempVMs[vmName].name) self.tempVMs[vmName].groups = out.strip() res = re.match("VMState=", out) if res: # logging.debug("Found vmState: " + out + " added to " + self.tempVMs[vmName].name) state = out.strip().split("\"")[1].split("\"")[0] self.tempVMs[vmName].state = state res = re.match("CurrentSnapshotUUID=", out) if res: # logging.debug("Found snaps: " + out + " added to " + self.tempVMs[vmName].latestSnapUUID) latestSnap = out.strip().split("\"")[1].split("\"")[0] self.tempVMs[vmName].latestSnapUUID = latestSnap p.wait() try: #Set self.vms to our temporary -- did it this way to save time self.lock.acquire() logging.debug("VM: " + str(vmName) + "\r\nself.vms: " + str(self.vms) + "\r\nself.tempVMs: " + str(self.tempVMs)) self.vms[vmName] = self.tempVMs[vmName] finally: self.lock.release() logging.debug("runVMInfo(): Thread 2 completed: " + vmShowInfoCmd) except Exception: logging.error("Error in runVMInfo(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runVMInfo(): sub 1 " + str(self.writeStatus)) def runConfigureVMNet(self, vmName, netNum, netName): try: logging.debug("VBoxManage: runConfigureVMNet(): instantiated") self.readStatus = VMManage.MANAGER_READING vmUUID = "" try: self.lock.acquire() vmUUID = str(self.vms[vmName].UUID) finally: self.lock.release() logging.debug("runConfigureVMNet(): adding 1 " + str(self.writeStatus)) vmConfigVMCmd = self.vmanage_path + " modifyvm " + vmUUID + " --nic" + str( netNum) + " intnet " + " --intnet" + str(netNum) + " " + str( netName) + " --cableconnected" + str(netNum) + " on " logging.debug("runConfigureVMNet(): Running " + vmConfigVMCmd) subprocess.check_output(shlex.split(vmConfigVMCmd, posix=self.POSIX), encoding='utf-8') logging.debug("runConfigureVMNet(): Thread completed") except Exception: logging.error("runConfigureVMNet() Error: " + " cmd: " + vmConfigVMCmd) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runConfigureVMNet(): sub 1 " + str(self.writeStatus)) def runVMCmd(self, cmd): logging.debug("VBoxManageWin: runVMCmd(): instantiated") try: self.readStatus = VMManage.MANAGER_READING logging.debug("runVMCmd(): adding 1 " + str(self.writeStatus)) vmCmd = self.vmanage_path + " " + cmd logging.debug("runVMCmd(): Running " + vmCmd) p = Popen(shlex.split(vmCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': logging.debug("output line: " + out) p.wait() logging.debug("runVMCmd(): Thread completed") except Exception: logging.error("runVMCmd() Error: " + " cmd: " + cmd) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runVMCmd(): sub 1 " + str(self.writeStatus)) def getVMStatus(self, vmName): logging.debug("VBoxManage: getVMStatus(): instantiated " + vmName) exists = False try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("getVMStatus(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 resVM = self.vms[vmName] #Don't want to rely on python objects in case we go with 3rd party clients in the future return { "vmName": resVM.name, "vmUUID": resVM.UUID, "setupStatus": resVM.setupStatus, "vmState": resVM.state, "adaptorInfo": resVM.adaptorInfo, "groups": resVM.groups, "latestSnapUUID": resVM.latestSnapUUID } finally: self.lock.release() def getManagerStatus(self): logging.debug("VBoxManage: getManagerStatus(): instantiated") vmStatus = {} try: self.lock.acquire() for vmName in self.vms: resVM = self.vms[vmName] vmStatus[resVM.name] = { "vmUUID": resVM.UUID, "setupStatus": resVM.setupStatus, "vmState": resVM.state, "adaptorInfo": resVM.adaptorInfo, "groups": resVM.groups } finally: self.lock.release() return { "readStatus": self.readStatus, "writeStatus": self.writeStatus, "vmstatus": vmStatus } def importVM(self, filepath): logging.debug("VBoxManage: importVM(): instantiated") cmd = "import \"" + filepath + "\" --options keepallmacs" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 def snapshotVM(self, vmName): logging.debug("VBoxManage: snapshotVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("snapshotVM(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 cmd = " snapshot " + str(self.vms[vmName].UUID) + " take snapshot" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def exportVM(self, vmName, filepath): logging.debug("VBoxManage: exportVM(): instantiated") #first remove any quotes that may have been entered before (because we will add some after we add the file and extension) try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("exportVM(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 filepath = filepath.replace("\"", "") exportfilename = os.path.join(filepath, vmName + ".ova") cmd = "export " + self.vms[ vmName].UUID + " -o \"" + exportfilename + "\" --iso" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def startVM(self, vmName): logging.debug("VBoxManage: startVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("startVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 cmd = "startvm " + str(self.vms[vmName].UUID) + " --type headless" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def pauseVM(self, vmName): logging.debug("VBoxManage: pauseVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("pauseVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 cmd = "controlvm " + str(self.vms[vmName].UUID) + " pause" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def suspendVM(self, vmName): logging.debug("VBoxManage: suspendVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("suspendVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 cmd = "controlvm " + str(self.vms[vmName].UUID) + " savestate" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def stopVM(self, vmName): logging.debug("VBoxManage: stopVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("stopVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 cmd = "controlvm " + str(self.vms[vmName].UUID) + " poweroff" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release() def removeVM(self, vmName): logging.debug("VBoxManage: removeVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("removeVM(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return -1 self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runRemoveVM, args=(vmName, str(self.vms[vmName].UUID))) t.start() return 0 finally: self.lock.release() def runRemoveVM(self, vmName, vmUUID): logging.debug("VBoxManage: runRemoveVM(): instantiated") try: self.readStatus = VMManage.MANAGER_READING logging.debug("runRemoveVM(): adding 1 " + str(self.writeStatus)) vmCmd = self.vmanage_path + " unregistervm " + vmUUID + " --delete" logging.debug("runRemoveVM(): Running " + vmCmd) success = False p = Popen(shlex.split(vmCmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stderr.readline() if out == '' and p.poll() != None: break if out != '': logging.debug("output line: " + out) if "100%" in out: success = True p.wait() if success: try: self.lock.acquire() del self.vms[vmName] finally: self.lock.release() logging.debug("runRemoveVM(): Thread completed") except Exception: logging.error("runRemoveVM() Error: " + " vmCmd: " + vmCmd) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runRemoveVM(): sub 1 " + str(self.writeStatus)) def cloneVMConfigAll(self, vmName, cloneName, cloneSnapshots, linkedClones, groupName, internalNets, vrdpPort, refreshVMInfo=False): logging.debug("VBoxManage: cloneVMConfigAll(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("cloneVMConfigAll(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 finally: self.lock.release() if refreshVMInfo == True: self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 #runVMInfo obtains it's own lock self.runVMInfo(vmName) self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runCloneVMConfigAll, args=(vmName, cloneName, cloneSnapshots, linkedClones, groupName, internalNets, vrdpPort)) t.start() return 0 def runCloneVMConfigAll(self, vmName, cloneName, cloneSnapshots, linkedClones, groupName, internalNets, vrdpPort): logging.debug("VBoxManage: runCloneVMConfigAll(): instantiated") try: self.readStatus = VMManage.MANAGER_READING logging.debug("runCloneVMConfigAll(): adding 1 " + str(self.writeStatus)) #first clone #Check that vm does exist try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("runCloneVMConfigAll(): " + vmName + " not found in list of known vms: \r\n" + str(vmName)) return finally: self.lock.release() # clone the VM self.writeStatus += 1 self.runCloneVM(vmName, cloneName, cloneSnapshots, linkedClones, groupName) #netsetup try: self.lock.acquire() exists = cloneName in self.vms if not exists: logging.error("runCloneVMConfigAll(): " + cloneName + " not found in list of known vms: \r\n" + str(cloneName)) return else: cloneUUID = str(self.vms[cloneName].UUID) finally: self.lock.release() self.writeStatus += 1 self.runConfigureVMNets(cloneName, internalNets) #vrdp setup (if applicable) if vrdpPort != None: self.writeStatus += 1 self.runEnableVRDP(cloneName, vrdpPort) #create snap snapcmd = self.vmanage_path + " snapshot " + cloneUUID + " take snapshot" logging.debug("runCloneVMConfigAll(): Running " + snapcmd) p = Popen(shlex.split(snapcmd, posix=self.POSIX), stdout=PIPE, stderr=PIPE, encoding="utf-8") while True: out = p.stdout.readline() if out == '' and p.poll() != None: break if out != '': logging.debug("runCloneVMConfigAll(): snapproc out: " + out) p.wait() logging.debug("runCloneVMConfigAll(): Thread completed") except Exception: logging.error( "runCloneVMConfigAll(): Error in runCloneVMConfigAll(): An error occured " ) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runCloneVMConfigAll(): sub 1 " + str(self.writeStatus)) def cloneVM(self, vmName, cloneName, cloneSnapshots, linkedClones, groupName, refreshVMInfo=False): logging.debug("VBoxManage: cloneVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("cloneVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 finally: self.lock.release() if refreshVMInfo == True: self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 #runVMInfo obtains it's own lock self.runVMInfo(vmName) self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runCloneVM, args=(vmName, cloneName, cloneSnapshots, linkedClones, groupName)) t.start() return 0 def runCloneVM(self, vmName, cloneName, cloneSnapshots, linkedClones, groupName): logging.debug("VBoxManage: runCloneVM(): instantiated") try: self.readStatus = VMManage.MANAGER_READING logging.debug("runCloneVM(): adding 1 " + str(self.writeStatus)) #First check that the clone doesn't exist: try: self.lock.acquire() exists = cloneName in self.vms if exists: logging.error( "runCloneVM(): A VM with the clone name already exists and is registered... skipping " + str(cloneName)) return else: vmUUID = str(self.vms[vmName].UUID) vmLatestSnapUUID = str(self.vms[vmName].latestSnapUUID) finally: self.lock.release() ###Only time cloneName is used instead of UUID, because it doesn't yet exist..." tmpCloneName = cloneName if " " in tmpCloneName and not tmpCloneName.startswith( "\"") and not tmpCloneName.endswith("\""): tmpCloneName = "\"" + str(tmpCloneName) + "\"" #Call runVMCommand cloneCmd = self.vmanage_path + " clonevm " + vmUUID + " --register" + " --options=keepallmacs" #NOTE, the following logic is not in error. Linked clone can only be created from a snapshot. if cloneSnapshots == 'true': #linked Clones option requires a cloneSnapshotUUID to be specified if linkedClones == 'true' and vmLatestSnapUUID != "": logging.debug("runCloneVM(): using linked clones") cloneCmd += " --options " cloneCmd += " link " cloneCmd += " --snapshot " + vmLatestSnapUUID else: cloneCmd += " --mode " cloneCmd += " all " #cloneCmd += " --options keepallmacs " cloneCmd += " --name " cloneCmd += str(tmpCloneName) logging.debug("runCloneVM(): executing: " + str(cloneCmd)) result = subprocess.check_output(shlex.split(cloneCmd, posix=self.POSIX), encoding='utf-8') #groupCmd = [self.vmanage_path, "modifyvm", tmpCloneName, "--groups", groupName] groupCmd = self.vmanage_path + " modifyvm " + str( tmpCloneName) + " --groups " + str(groupName) logging.debug("runCloneVM(): placing into group: " + str(groupName)) logging.debug("runCloneVM(): executing: " + str(groupCmd)) result = subprocess.check_output(shlex.split(groupCmd, posix=self.POSIX), encoding='utf-8') logging.debug("runCloneVM(): Clone Created: " + str(tmpCloneName) + " and placed into group: " + groupName) #since we added a VM, now we have to add it to the known list logging.debug("runCloneVM(): Adding: " + str(tmpCloneName) + " to known VMs") self.writeStatus += 1 self.runVMInfo(tmpCloneName) except Exception: logging.error( "runCloneVM(): Error in runCloneVM(): An error occured; it could be due to a missing snapshot for the VM" ) exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runCloneVM(): sub 1 " + str(self.writeStatus)) def enableVRDPVM(self, vmName, vrdpPort): logging.debug("VBoxManage: enabledVRDP(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("enabledVRDP(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runEnableVRDP, args=(vmName, vrdpPort)) t.start() return 0 finally: self.lock.release() def runEnableVRDP(self, vmName, vrdpPort): logging.debug("VBoxManage: runEnabledVRDP(): instantiated") try: self.readStatus = VMManage.MANAGER_READING logging.debug("runEnableVRDP(): adding 1 " + str(self.writeStatus)) #vrdpCmd = [self.vmanage_path, "modifyvm", vmName, "--vrde", "on", "--vrdeport", str(vrdpPort)] vrdpCmd = self.vmanage_path + " modifyvm " + str( vmName) + " --vrde " + " on " + " --vrdeport " + str(vrdpPort) logging.debug("runEnableVRDP(): setting up vrdp for " + vmName) logging.debug("runEnableVRDP(): executing: " + str(vrdpCmd)) result = subprocess.check_output(shlex.split(vrdpCmd, posix=self.POSIX), encoding='utf-8') #now these settings will help against the issue when users #can't reconnect after an abrupt disconnect #https://www.virtualbox.org/ticket/2963 vrdpCmd = self.vmanage_path + " modifyvm " + str( vmName ) + " --vrdemulticon " + " on " #" --vrdereusecon " + " on " + " --vrdemulticon " + " off" logging.debug( "runEnableVRDP(): Setting disconnect on new connection for " + vmName) logging.debug("runEnableVRDP(): executing: " + str(vrdpCmd)) result = subprocess.check_output(shlex.split(vrdpCmd, posix=self.POSIX), encoding='utf-8') logging.debug("runEnableVRDP(): completed") except Exception: logging.error( "runEnableVRDP(): Error in runEnableVRDP(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) finally: self.readStatus = VMManage.MANAGER_IDLE self.writeStatus -= 1 logging.debug("runEnableVRDP(): sub 1 " + str(self.writeStatus)) def restoreLatestSnapVM(self, vmName): logging.debug("VBoxManage: restoreLatestSnapVM(): instantiated") #check to make sure the vm is known, if not should refresh or check name: try: self.lock.acquire() exists = vmName in self.vms if not exists: logging.error("restoreLatestSnapVM(): " + vmName + " not found in list of known vms: \r\n" + str(self.vms)) return -1 cmd = "snapshot " + str(self.vms[vmName].UUID) + " restorecurrent" self.readStatus = VMManage.MANAGER_READING self.writeStatus += 1 t = threading.Thread(target=self.runVMCmd, args=(cmd, )) t.start() return 0 finally: self.lock.release()
def __init__(self, parent=None): logging.debug("MainApp:init() instantiated") super().__init__() self.baseWidgets = {} self.vmWidgets = {} self.materialWidgets = {} self.cf = SystemConfigIO() self.ec = ExperimentConfigIO.getInstance() self.statusBar = QStatusBar() self.setMinimumSize(670, 565) quit = QAction("Quit", self) quit.triggered.connect(self.closeEvent) self.setWindowTitle("ARL South RES v0.1") self.tabWidget = QtWidgets.QTabWidget() self.tabWidget.setGeometry(QtCore.QRect(0, 15, 668, 565)) self.tabWidget.setObjectName("tabWidget") # Configuration Window (windowBox) contains: ## windowBoxHLayout contains: ###experimentTree (Left) ###basedataStackedWidget (Right) self.windowWidget = QtWidgets.QWidget() self.windowWidget.setObjectName("windowWidget") self.windowBoxHLayout = QtWidgets.QHBoxLayout() #self.windowBoxHLayout.setContentsMargins(0, 0, 0, 0) self.windowBoxHLayout.setObjectName("windowBoxHLayout") self.windowWidget.setLayout(self.windowBoxHLayout) self.experimentTree = QtWidgets.QTreeWidget() self.experimentTree.itemSelectionChanged.connect(self.onItemSelected) self.experimentTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.experimentTree.customContextMenuRequested.connect( self.showContextMenu) self.experimentTree.setEnabled(True) self.experimentTree.setMinimumSize(200, 521) self.experimentTree.setMaximumWidth(350) self.experimentTree.setObjectName("experimentTree") self.experimentTree.headerItem().setText(0, "Experiments") self.experimentTree.setSortingEnabled(False) self.windowBoxHLayout.addWidget(self.experimentTree) self.basedataStackedWidget = QStackedWidget() self.basedataStackedWidget.setObjectName("basedataStackedWidget") self.basedataStackedWidget.setEnabled(False) self.windowBoxHLayout.addWidget(self.basedataStackedWidget) self.tabWidget.addTab(self.windowWidget, "Configuration") # VBox Actions Tab self.experimentActionsWidget = ExperimentActionsWidget( statusBar=self.statusBar) self.experimentActionsWidget.setObjectName("experimentActionsWidget") self.tabWidget.addTab(self.experimentActionsWidget, "Experiment Actions") # Remote Connections Tab self.connectionWidget = ConnectionWidget(statusBar=self.statusBar) self.connectionWidget.setObjectName("connectionsWidget") self.tabWidget.addTab(self.connectionWidget, "Remote Connections") #Create the bottom layout so that we can access the status bar self.bottomLayout = QHBoxLayout() self.statusBar.showMessage("Loading GUI...") self.bottomLayout.addWidget(self.statusBar) self.saveButton = QtWidgets.QPushButton("Save Current") self.saveButton.clicked.connect(self.saveExperimentButton) self.saveButton.setEnabled(False) self.bottomLayout.addWidget(self.saveButton) self.populateUi() self.setupContextMenus() self.initMenu() self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(self.mainMenu) self.mainLayout.addWidget(self.tabWidget) self.mainLayout.addLayout(self.bottomLayout) self.setLayout(self.mainLayout) #self.setCentralWidget(self.outerBox) self.tabWidget.setCurrentIndex(0) #self.statusBar.showMessage("Finished Loading GUI Components") # Plugin Section self.tabWidget.addTab(CTFi2GUI(), "CTFi2")
class ConnectionActionDialog(QDialog): def __init__(self, parent, configname, actionname, experimentHostname, rdpBrokerHostname="<unspecified>", users_file="", itype="", name=""): logging.debug("ConnectionActionDialog(): instantiated") super(ConnectionActionDialog, self).__init__(parent) self.parent = parent self.eco = ExperimentConfigIO.getInstance() self.s = SystemConfigIO() self.configname = configname self.actionname = actionname self.experimentHostname = experimentHostname self.usersFile = users_file self.itype = itype self.name = name if rdpBrokerHostname.strip() == "": self.rdpBrokerHostname = "<unspecified>" self.setEnabled(False) else: self.rdpBrokerHostname = rdpBrokerHostname self.cm = ConnectionManage() self.setMinimumWidth(450) self.createFormGroupBox() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle(str(actionname) + " Connection") def createFormGroupBox(self): self.formGroupBox = QGroupBox("Connection Information") self.layout = QFormLayout() self.experimentHostnameLineEdit = QLineEdit(self.experimentHostname) self.experimentHostnameLineEdit.setEnabled(False) self.layout.addRow(QLabel("VM Server IP:"), self.experimentHostnameLineEdit) self.hostnameLineEdit = QLineEdit(self.rdpBrokerHostname) self.hostnameLineEdit.setEnabled(False) self.layout.addRow(QLabel("RDP Broker Hostname/IP:"), self.hostnameLineEdit) mgmusername = "" mgmpassword = "" url = "/guacamole" method = "HTTP" cachedCreds = self.eco.getConfigRDPBrokerCreds(self.configname) if cachedCreds != None: mgmusername = cachedCreds[0] mgmpassword = cachedCreds[1] url = cachedCreds[2] method = cachedCreds[3] self.usernameLineEdit = QLineEdit(mgmusername) self.passwordLineEdit = QLineEdit(mgmpassword) self.passwordLineEdit.setEchoMode(QLineEdit.Password) if self.actionname != "Open": self.layout.addRow(QLabel("Management Username:"******"Management Password:"******"URL Path:"), self.urlPathLineEdit) self.methodComboBox = QComboBox() self.methodComboBox.addItem("HTTP") self.methodComboBox.addItem("HTTPS") if method == "HTTP": self.methodComboBox.setCurrentIndex(0) else: self.methodComboBox.setCurrentIndex(1) self.layout.addRow(QLabel("Method:"), self.methodComboBox) self.maxConnectionsLineEdit = QLineEdit("1") self.heightLineEdit = QLineEdit("1400") self.widthLineEdit = QLineEdit("1050") self.bitdepthComboBox = QComboBox() self.bitdepthComboBox.addItem("256 colors (8-bit)") self.bitdepthComboBox.addItem("Low color (16-bit)") self.bitdepthComboBox.addItem("True color (24-bit)") self.bitdepthComboBox.addItem("True color (32-bit)") self.bitdepthComboBox.setCurrentIndex(1) self.usersFileLabel = QLineEdit(self.usersFile) self.usersFileLabel.setEnabled(False) if self.actionname == "Add": #Need to make a function to create more than one user to a single instance self.layout.addRow(QLabel("Users File: "), self.usersFileLabel) self.layout.addRow(QLabel("Max Connections Per User:"******"Display Height:"), self.heightLineEdit) self.layout.addRow(QLabel("Display Width:"), self.widthLineEdit) self.layout.addRow(QLabel("Bit Depth:"), self.bitdepthComboBox) if self.actionname == "Remove": self.layout.addRow(QLabel("Users File: "), self.usersFileLabel) self.formGroupBox.setLayout(self.layout) def exec_(self): logging.debug("ConnectionActionDialog(): exec_() instantiated") result = super(ConnectionActionDialog, self).exec_() if str(result) == str(1): logging.debug("dialog_response(): OK was pressed") if self.actionname == "Add": bitDepth = self.bitdepthComboBox.currentText() if bitDepth == "256 colors (8-bit)": bitDepth = "8" elif bitDepth == "Low color (16-bit)": bitDepth = "16" elif bitDepth == "True color (24-bit)": bitDepth = "24" elif bitDepth == "True color (32-bit)": bitDepth = "32" self.args = [self.hostnameLineEdit.text(), self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText(), "1", self.maxConnectionsLineEdit.text(), self.heightLineEdit.text(), self.widthLineEdit.text(), bitDepth, self.usersFileLabel.text(), self.itype, self.name] elif self.actionname == "Remove": self.args = [self.hostnameLineEdit.text(), self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText(), self.usersFileLabel.text(), self.itype, self.name] elif self.actionname == "Clear": self.args = [self.hostnameLineEdit.text(), self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText()] elif self.actionname == "Refresh": self.args = [self.hostnameLineEdit.text(), self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText()] elif self.actionname == "Open": #get all of the connections from the currently selected item userpool = UserPool() usersConns = userpool.generateUsersConns(self.configname, creds_file=self.usersFile) vmuser_mapping = {} for (username, password) in usersConns: for conn in usersConns[(username, password)]: cloneVMName = conn[0] vmuser_mapping[cloneVMName] = (username, password) #get all vms based on what's selected tentativeVMs = self.eco.getValidVMsFromTypeName(self.configname, self.itype, self.name) #get user/password from selected vms and store those in the list of users to open usersToOpen = {} for vm in tentativeVMs: if vm in vmuser_mapping: usersToOpen[vmuser_mapping[vm]] = True logging.debug(str(usersToOpen)) else: pass if self.actionname == "Refresh": self.eco.storeConfigRDPBrokerCreds(self.configname, self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText()) crd = ConnectionRetrievingDialog(self.parent, self.args).exec_() return crd elif self.actionname == "Open": self.eco.storeConfigRDPBrokerCreds(self.configname, self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText()) pathToBrowser = self.s.getConfig()["BROWSER"]["BROWSER_PATH"] browserArgs = self.s.getConfig()["BROWSER"]["ARGS"] url = self.rdpBrokerHostname+self.urlPathLineEdit.text() cod = ConnectionOpeningDialog(self.parent, pathToBrowser, browserArgs, usersToOpen, url, self.methodComboBox.currentText()).exec_() return cod else: self.eco.storeConfigRDPBrokerCreds(self.configname, self.usernameLineEdit.text(), self.passwordLineEdit.text(), self.urlPathLineEdit.text(), self.methodComboBox.currentText()) cad = ConnectionActioningDialog(self.parent, self.configname, self.actionname, self.args).exec_() return (QMessageBox.Ok) return (QMessageBox.Cancel)
class ConfigurationDialog(QDialog): def __init__(self, parent): logging.debug("ConfigurationDialog(): instantiated") super(ConfigurationDialog, self).__init__(parent) self.parent = parent self.s = SystemConfigIO() self.setMinimumWidth(435) self.createFormGroupBox() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) mainLayout = QVBoxLayout() mainLayout.addWidget(self.formGroupBox) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("RES Configuration") def createFormGroupBox(self): self.formGroupBox = QGroupBox( "Configuration Paths (don't change unless you really know what you're doing)" ) self.layout = QFormLayout() self.virtualboxPathLineEdit = QLineEdit( self.s.getConfig()["VBOX"]["VBOX_PATH"]) self.layout.addRow(QLabel("VirtualBox Path:"), self.virtualboxPathLineEdit) self.vmanagePathLineEdit = QLineEdit( self.s.getConfig()["VBOX"]["VMANAGE_PATH"]) self.layout.addRow(QLabel("VBoxManage Path:"), self.vmanagePathLineEdit) self.experimentPathLineEdit = QLineEdit( self.s.getConfig()["EXPERIMENTS"]["EXPERIMENTS_PATH"]) self.layout.addRow(QLabel("Experiments Data Path:"), self.experimentPathLineEdit) self.temporaryPathLineEdit = QLineEdit( self.s.getConfig()["EXPERIMENTS"]["TEMP_DATA_PATH"]) self.layout.addRow(QLabel("Temporary Data Path:"), self.temporaryPathLineEdit) self.formGroupBox.setLayout(self.layout) def exec_(self): logging.debug("ConfigurationDialog(): exec_() instantiated") result = super(ConfigurationDialog, self).exec_() if str(result) == str(1): logging.debug("dialog_response(): OK was pressed") # For each value on the form, write it to the config file self.s.writeConfig("VBOX", "VBOX_PATH", self.virtualboxPathLineEdit.text()) self.s.writeConfig("VBOX", "VMANAGE_PATH", self.vmanagePathLineEdit.text()) self.s.writeConfig("EXPERIMENTS", "EXPERIMENTS_PATH", self.experimentPathLineEdit.text()) self.s.writeConfig("EXPERIMENTS", "TEMP_DATA_PATH", self.temporaryPathLineEdit.text()) return (QMessageBox.Ok) return (QMessageBox.Cancel)
class PackageManageVBox(PackageManage): def __init__(self, vmManage, experimentManage): logging.debug("PackageManageVBox(): instantiated") PackageManage.__init__(self) self.vmManage = vmManage self.em = experimentManage self.s = SystemConfigIO() self.s.readConfig() #abstractmethod def importPackage(self, resfilename, runVagrantProvisionScript=False): logging.debug("importPackage(): instantiated") t = threading.Thread(target=self.runImportPackage, args=(resfilename, )) t.start() return 0 def runImportPackage(self, resfilename, vagrantProvisionScriptfilename=None): logging.debug("runImportPackage(): instantiated") try: self.writeStatus = PackageManage.PACKAGE_MANAGE_IMPORTING #Unzip the file contents # get path for temporary directory to hold uncompressed files logging.debug("runImportPackage(): unzipping contents") tmpPathBase = os.path.join( self.s.getConfig()['EXPERIMENTS']['TEMP_DATA_PATH'], "import") assumedExperimentName = os.path.basename(resfilename) assumedExperimentName = os.path.splitext(assumedExperimentName)[0] tmpPathBaseImportedExperiment = os.path.join( tmpPathBase, assumedExperimentName) targetPathBase = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], assumedExperimentName) self.unzipWorker(resfilename, tmpPathBase) logging.debug("runImportPackage(): completed unzipping contents") tmpPathVMs = os.path.join(tmpPathBase, assumedExperimentName, "VMs") #For ova files #call vmManage to import VMs as specified in config file; wait and query the vmManage status, and then set the complete status # Get all files that end with .ova #import and then snapshot vmFilenames = [] if os.path.exists(tmpPathVMs): vmFilenames = os.listdir(tmpPathVMs) logging.debug("runImportPackage(): Unzipped files: " + str(vmFilenames)) vmNum = 1 for vmFilename in vmFilenames: if vmFilename.endswith(".ova"): logging.debug("runImportPackage(): Importing " + str(vmFilename) + " into VirtualBox...") logging.debug("Importing VM " + str(vmNum) + " of " + str(len(vmFilenames))) #Import the VM using a system call self.importVMWorker(os.path.join(tmpPathVMs, vmFilename)) #since we added a new VM, we have to refresh ##TODO: replace with updateVMByName() self.vmManage.refreshAllVMInfo() result = self.vmManage.getManagerStatus()["writeStatus"] while result != self.vmManage.MANAGER_IDLE: #waiting for manager to finish query... result = self.vmManage.getManagerStatus()["writeStatus"] time.sleep(.1) #now take a snapshot self.snapshotVMWorker(os.path.join(vmFilename[:-4])) vmNum = vmNum + 1 #TODO: move all unzipped files (except ovas) to experiment path) #remove experiment from experiment folder if it already exists if os.path.exists(tmpPathBaseImportedExperiment) == False: logging.error( "Experiment folder not found after decompressing files... Skipping: " + str(tmpPathBaseImportedExperiment)) self.writeStatus = PackageManage.PACKAGE_MANAGE_COMPLETE return None logging.debug( "runImportPackage(): copying experiment files to experiment folder: " + str(targetPathBase)) if os.path.exists(targetPathBase): logging.error( "Experiment path already exists. Removing and copying anyway..." + str(targetPathBase)) shutil.rmtree(targetPathBase, ignore_errors=True) #copy all files to experiment folder shutil.copytree(tmpPathBaseImportedExperiment, targetPathBase, ignore=shutil.ignore_patterns("*.ova")) #now remove the temporary data folder logging.debug("runExportPackage(): removing temporary folder: " + str(tmpPathBaseImportedExperiment)) if os.path.exists(tmpPathBaseImportedExperiment): shutil.rmtree(tmpPathBaseImportedExperiment, ignore_errors=True) #double check to see if path was removed or not... if os.path.exists(tmpPathBaseImportedExperiment): logging.error( "runExportPackage(): Could not remove temporary directory: " + str(tmpPathBaseImportedExperiment)) self.writeStatus = PackageManage.PACKAGE_MANAGE_COMPLETE except FileNotFoundError: logging.error("Error in runImportPackage(): File not found") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None except: logging.error("Error in runImportPackage(): An error occured") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None finally: self.writeStatus = PackageManage.PACKAGE_MANAGE_COMPLETE return None def unzipWorker(self, resfilename, tmpOutPath): logging.debug("unzipWorker() initiated " + str(resfilename)) zipPath = resfilename block_size = 1048576 try: if os.path.exists(zipPath) == False: logging.error( "unzipWorker(): path to zip not found... Skipping..." + str(zipPath)) return z = zipfile.ZipFile(zipPath, 'r') outputPath = os.path.join(tmpOutPath) members_list = z.namelist() currmem_num = 0 for entry_name in members_list: if entry_name[-1] is '/': # if entry is a directory continue logging.debug("unzipWorker(): unzipping " + str(entry_name)) # increment our file progress counter currmem_num = currmem_num + 1 entry_info = z.getinfo(entry_name) i = z.open(entry_name) if not os.path.exists(outputPath): os.makedirs(outputPath) filename = os.path.join(outputPath, entry_name) file_dirname = os.path.dirname(filename) if not os.path.exists(file_dirname): os.makedirs(file_dirname) o = open(filename, 'wb') offset = 0 int_val = 0 while True: b = i.read(block_size) offset += len(b) logging.debug("unzipWorker(): file_size: " + str(float(entry_info.file_size))) logging.debug("unzipWorker(): Offset: " + str(offset)) if entry_info.file_size > 0.1: status = float(offset) / float( entry_info.file_size) * 100. else: status = 0 logging.debug("unzipWorker(): Status: " + str(status)) if int(status) > int_val: int_val = int(status) logging.debug("unzipWorker(): Progress: " + str(float(int_val / 100.))) logging.debug("unzipWorker(): Processing file " + str(currmem_num) + "/" + str(len(members_list)) + ":\r\n" + entry_name + "\r\nExtracting: " + str(int_val) + " %") if b == b'': break #logging.debug("unzipWorker(): Writing out file data for file: " + str(entry_name) + " data: " + str(b)) o.write(b) logging.debug("unzipWorker(): Finished processing file: " + str(entry_name)) i.close() o.close() except FileNotFoundError: logging.error("Error in unzipWorker(): File not found: ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) except Exception: logging.error("Error in unzipWorker(): An error occured ") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) def importVMWorker(self, vmFilepath): logging.debug("importVMWorker(): instantiated") self.vmManage.importVM(vmFilepath) res = self.vmManage.getManagerStatus() logging.debug("Waiting for import to complete...") while res["writeStatus"] != self.vmManage.MANAGER_IDLE: time.sleep(.1) logging.debug("Waiting for import vm to complete...") res = self.vmManage.getManagerStatus() logging.debug("Import complete...") logging.debug("importVMWorker(): complete") def snapshotVMWorker(self, vmName): logging.debug("snapshotVMWorker(): instantiated") self.vmManage.snapshotVM(vmName) res = self.vmManage.getManagerStatus() logging.debug("Waiting for snapshot create to complete...") while res["writeStatus"] != self.vmManage.MANAGER_IDLE: time.sleep(.1) logging.debug("Waiting for snapshot vm to complete...") res = self.vmManage.getManagerStatus() logging.debug("snapshotVMWorker(): complete") #abstractmethod def exportPackage(self, experimentname, exportpath): logging.debug("exportPackage: instantiated") t = threading.Thread(target=self.runExportPackage, args=( experimentname, exportpath, )) t.start() return 0 def runExportPackage(self, experimentname, exportpath): logging.debug("runExportPackage(): instantiated") try: self.writeStatus = PackageManage.PACKAGE_MANAGE_EXPORTING #get/create the temp directory to hold all experimentDatapath = os.path.join( self.s.getConfig()['EXPERIMENTS']['EXPERIMENTS_PATH'], experimentname) tmpPathBase = os.path.join( self.s.getConfig()['EXPERIMENTS']['TEMP_DATA_PATH'], "export", experimentname) tmpPathVMs = os.path.join(tmpPathBase, "VMs") tmpPathMaterials = os.path.join(tmpPathBase, "Materials") tmpPathExperiments = os.path.join(tmpPathBase, "Experiments") exportfilename = os.path.join(exportpath, experimentname + ".res") #copy all files to temp folder logging.debug( "runExportPackage(): copying experiment files to temporary folder: " + str(tmpPathBase)) if os.path.exists(tmpPathBase): shutil.rmtree(tmpPathBase, ignore_errors=True) #have to check again if path was removed or not... if os.path.exists(tmpPathBase): logging.error( "runExportPackage(): Could not remove directory. Cancelling export: " + str(tmpPathBase)) self.writeStatus = PackageManage.PACKAGE_MANAGE_IDLE return shutil.copytree(experimentDatapath, tmpPathBase) #create any folders that should exist but don't if os.path.exists(tmpPathVMs) == False: os.makedirs(tmpPathVMs) if os.path.exists(tmpPathMaterials) == False: os.makedirs(tmpPathMaterials) if os.path.exists(tmpPathExperiments) == False: os.makedirs(tmpPathExperiments) #export vms that are part of this experiment to the temp folder vmNames = self.em.getExperimentVMNames(experimentname) logging.debug( "runExportPackage(): preparing to export experiment vms: " + str(vmNames)) for vmName in vmNames: logging.debug("runExportPackage(): exporting: " + str(vmName)) self.exportVMWorker(vmName, tmpPathVMs) logging.debug("runExportPackage(): exporting of " + str(vmName) + " complete") #add to zip everything that exists in the experiment folder logging.debug("runExportPackage(): zipping files") self.zipWorker(tmpPathBase, exportfilename) logging.debug("runExportPackage(): completed zipping files") #now remove the temporary data folder logging.debug("runExportPackage(): removing temporary folder: " + str(tmpPathBase)) if os.path.exists(tmpPathBase): shutil.rmtree(tmpPathBase, ignore_errors=True) #double check to see if path was removed or not... if os.path.exists(tmpPathBase): logging.error( "runExportPackage(): Could not remove temporary directory: " + str(tmpPathBase)) self.writeStatus = PackageManage.PACKAGE_MANAGE_COMPLETE except FileNotFoundError: logging.error("Error in runExportPackage(): File not found") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None except: logging.error("Error in runExportPackage(): An error occured") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None finally: self.writeStatus = PackageManage.PACKAGE_MANAGE_COMPLETE return None def zipWorker(self, pathToAdd, zipfilename): logging.debug("zipWorker(): instantiated") try: logging.debug("zipWorker(): checking if destination path exists") zipBasePath = os.path.dirname(zipfilename) if os.path.exists(zipBasePath) == False: logging.debug( "zipWorker(): destination path does not exist; attempting to create it: " + str(zipBasePath)) os.makedirs(zipBasePath) if os.path.exists(pathToAdd): outZipFile = zipfile.ZipFile(zipfilename, 'w', zipfile.ZIP_STORED) # The root directory within the ZIP file. rootdir = os.path.basename(pathToAdd) for dirpath, dirnames, filenames in os.walk(pathToAdd): for filename in filenames: # Write the file named filename to the archive, # giving it the archive name 'arcname'. filepath = os.path.join(dirpath, filename) parentpath = os.path.relpath(filepath, pathToAdd) arcname = os.path.join(rootdir, parentpath) outZipFile.write(filepath, arcname) except FileNotFoundError: logging.error("Error in zipWorker(): File not found") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None except: logging.error("Error in zipWorker(): An error occured") exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_traceback) return None finally: return None def exportVMWorker(self, vmName, filepath): logging.debug("exportVMWorker(): instantiated") self.vmManage.refreshAllVMInfo() logging.debug("Waiting for export to complete...") result = self.vmManage.getManagerStatus()["writeStatus"] while result != self.vmManage.MANAGER_IDLE: #waiting for manager to finish query... result = self.vmManage.getManagerStatus()["writeStatus"] time.sleep(.1) self.vmManage.exportVM(vmName, filepath) res = self.vmManage.getManagerStatus() logging.debug("Waiting for export to complete...") while res["writeStatus"] != self.vmManage.MANAGER_IDLE: time.sleep(.1) logging.debug( "exportVMWorker(): Waiting for export vm to complete...") res = self.vmManage.getManagerStatus() logging.debug("Export complete...") #abstractmethod def getPackageManageStatus(self): logging.debug("getPackageManageStatus(): instantiated") return {"readStatus": self.readStatus, "writeStatus": self.writeStatus}