[virt-tools-list] [PATCH] Add oVirt nodeadmin code to repo
Darryl L. Pierce
dpierce at redhat.com
Mon Aug 16 15:08:17 UTC 2010
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/__init__.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,19 @@
+# __init__.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from nodeadmin import NodeAdmin
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/adddomain.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/adddomain.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,512 @@
+#!/usr/bin/env python
+#
+# adddomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import os
+from createmeter import CreateMeter
+from domainconfig import DomainConfig
+from configscreen import ConfigScreen
+import utils
+
+from virtinst import *
+
+VM_DETAILS_PAGE = 1
+LOCAL_INSTALL_PAGE = 2
+SELECT_CDROM_PAGE = 3
+SELECT_ISO_PAGE = 4
+NETWORK_INSTALL_PAGE = 5
+OS_TYPE_PAGE = 6
+OS_VARIANT_PAGE = 7
+RAM_CPU_PAGE = 8
+ENABLE_STORAGE_PAGE = 9
+LOCAL_STORAGE_PAGE = 10
+SELECT_POOL_PAGE = 11
+SELECT_VOLUME_PAGE = 12
+BRIDGE_PAGE = 13
+VIRT_DETAILS_PAGE = 14
+CONFIRM_PAGE = 15
+
+LOCATION="location"
+KICKSTART="kickstart"
+KERNELOPTS="kernel.options"
+OS_TYPE="os.type"
+OS_VARIANT="os.variant"
+MEMORY="memory"
+CPUS="cpus"
+
+class DomainConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScreen.__init__(self, "Create A New Virtual Machine")
+ self.__config = DomainConfig()
+ self.__config.set_architecture(self.get_libvirt().get_default_architecture())
+ self.__config.set_virt_type(self.get_libvirt().get_default_virt_type())
+
+ def get_elements_for_page(self, screen, page):
+ if page is VM_DETAILS_PAGE: return self.get_vm_details_page(screen)
+ elif page is LOCAL_INSTALL_PAGE: return self.get_local_install_page(screen)
+ elif page is SELECT_CDROM_PAGE: return self.get_select_cdrom_page(screen)
+ elif page is SELECT_ISO_PAGE: return self.get_select_iso_page(screen)
+ elif page is NETWORK_INSTALL_PAGE: return self.get_network_install_page(screen)
+ elif page is OS_TYPE_PAGE: return self.get_os_type_page(screen)
+ elif page is OS_VARIANT_PAGE: return self.get_os_variant_page(screen)
+ elif page is RAM_CPU_PAGE: return self.get_ram_and_cpu_page(screen)
+ elif page is ENABLE_STORAGE_PAGE: return self.get_enable_storage_page(screen)
+ elif page is LOCAL_STORAGE_PAGE: return self.get_local_storage_page(screen)
+ elif page is SELECT_POOL_PAGE: return self.get_select_pool_page(screen)
+ elif page is SELECT_VOLUME_PAGE: return self.get_select_volume_page(screen)
+ elif page is BRIDGE_PAGE: return self.get_bridge_page(screen)
+ elif page is VIRT_DETAILS_PAGE: return self.get_virt_details_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+ return []
+
+ def get_page_list(self):
+ return ["Virtual Machine Details",
+ "Local Installation Details",
+ "Setup CD-ROM Device",
+ "Setup ISO File",
+ "Setup Network Installation",
+ "Select Operating System Type",
+ "Select Operating System Variant",
+ "Set Memory Size",
+ "Enable Storage",
+ "Setup Local Storage",
+ "Select Storage Pool",
+ "Select Storage Volume",
+ "Setup Bridge",
+ "Review Virtual Machine Details",
+ "Confirm Virtual Machine"]
+
+ def validate_input(self, page, errors):
+ if page is VM_DETAILS_PAGE:
+ if len(self.__guest_name.value()) > 0:
+ if self.get_libvirt().domain_exists(self.__guest_name.value()):
+ errors.append("Guest name '%s' is already in use." % self.__guest_name.value())
+ else:
+ return True
+ else:
+ errors.append("Guest name must be a string between 0 and 50 characters.")
+ elif page is LOCAL_INSTALL_PAGE:
+ if self.__install_source.getSelection() == DomainConfig.INSTALL_SOURCE_CDROM:
+ return True
+ elif self.__install_source.getSelection() == DomainConfig.INSTALL_SOURCE_ISO:
+ return True
+ elif page is SELECT_CDROM_PAGE:
+ if self.__install_media.getSelection() != None:
+ if len(self.get_hal().list_installable_volumes()) == 0:
+ errors.append("No installable media is available.")
+ else:
+ return True
+ else:
+ errors.append("You must select an install media.")
+ elif page is SELECT_ISO_PAGE:
+ if len(self.__iso_path.value()) > 0:
+ if os.path.exists(self.__iso_path.value()):
+ if os.path.isfile(self.__iso_path.value()):
+ return True
+ else:
+ errors.append("%s is not a file." % self.__iso_path.value())
+ else:
+ errors.append("No such install media exists:")
+ errors.append(self.__iso_path.value())
+ else:
+ errors.append("An install media selection is required.")
+ elif page is NETWORK_INSTALL_PAGE:
+ if len(self.__install_url.value()) > 0:
+ return True
+ else:
+ errors.append("An install tree is required.")
+ elif page is OS_TYPE_PAGE: return True
+ elif page is OS_VARIANT_PAGE: return True
+ elif page is RAM_CPU_PAGE:
+ if (len(self.__memory.value()) > 0 and len(self.__cpus.value()) > 0) \
+ and (int(self.__memory.value()) > 0 and int(self.__cpus.value()) > 0):
+ return True
+ else:
+ if len(self.__memory.value()) == 0:
+ errors.append("A value must be entered for memory.")
+ elif int(self.__memory.value()) <= 0:
+ errors.append("A positive integer value must be entered for memory.")
+ if len(self.__cpus.value()) == 0:
+ errors.append("A value must be entered for CPUs.")
+ elif int(self.__cpus.value()) <= 0:
+ errors.append("A positive integer value must be entered for memory.")
+ elif page is ENABLE_STORAGE_PAGE: return True
+ elif page is LOCAL_STORAGE_PAGE:
+ if len(self.__storage_size.value()) > 0:
+ if float(self.__storage_size.value()) > 0:
+ return True
+ else:
+ errors.append("A positive value must be entered for the storage size.")
+ else:
+ errors.append("A value must be entered for the storage size.")
+ elif page is SELECT_POOL_PAGE:
+ if self.__storage_pool.getSelection() is not None:
+ return True
+ else:
+ errors.append("Please select a storage pool.")
+ elif page is SELECT_VOLUME_PAGE:
+ if self.__storage_volume.getSelection() is not None:
+ return True
+ else:
+ errors.append("Please select a storage volume.")
+ elif page is BRIDGE_PAGE:
+ if self.__network_bridges.getSelection() != None:
+ if len(self.__mac_address.value()) > 0:
+ # TODO: regex check the format
+ return True
+ else:
+ errors.append("MAC address must be supplied.")
+ else:
+ errors.append("A network bridge must be selected.")
+ elif page is VIRT_DETAILS_PAGE:
+ if self.__virt_types.getSelection() != None and self.__architectures.getSelection() != None:
+ return True
+ if self.__virt_types.getSelection() is None:
+ errors.append("Please select a virtualization type.")
+ if self.__architectures.getSelection() is None:
+ errors.append("Please selection an architecture.")
+ elif page is CONFIRM_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is VM_DETAILS_PAGE:
+ self.__config.set_guest_name(self.__guest_name.value())
+ self.__config.set_install_type(self.__install_type.getSelection())
+ elif page is LOCAL_INSTALL_PAGE:
+ self.__config.set_use_cdrom_source(self.__install_source.getSelection() == DomainConfig.INSTALL_SOURCE_CDROM)
+ elif page is SELECT_CDROM_PAGE:
+ self.__config.set_install_media(self.__install_media.getSelection())
+ elif page is SELECT_ISO_PAGE:
+ self.__config.set_iso_path(self.__iso_path.value())
+ elif page is NETWORK_INSTALL_PAGE:
+ self.__config.set_install_url(self.__install_url.value())
+ self.__config.set_kickstart_url(self.__kickstart_url.value())
+ self.__config.set_kernel_options(self.__kernel_options.value())
+ elif page is OS_TYPE_PAGE:
+ self.__config.set_os_type(self.__os_types.getSelection())
+ elif page is OS_VARIANT_PAGE:
+ self.__config.set_os_variant(self.__os_variants.getSelection())
+ elif page is RAM_CPU_PAGE:
+ self.__config.set_memory(int(self.__memory.value()))
+ self.__config.set_cpus(int(self.__cpus.value()))
+ elif page is ENABLE_STORAGE_PAGE:
+ self.__config.set_enable_storage(self.__enable_storage.value())
+ if self.__storage_type.getSelection() == DomainConfig.NEW_STORAGE:
+ self.__config.set_use_local_storage(True)
+ elif self.__storage_type.getSelection() == DomainConfig.EXISTING_STORAGE:
+ self.__config.set_use_local_storage(False)
+ elif page is LOCAL_STORAGE_PAGE:
+ self.__config.set_storage_size(float(self.__storage_size.value()))
+ self.__config.set_allocate_storage(self.__allocate_storage.value())
+ elif page is SELECT_POOL_PAGE:
+ self.__config.set_use_local_storage(False)
+ self.__config.set_storage_pool(self.__storage_pool.getSelection())
+ elif page is SELECT_VOLUME_PAGE:
+ self.__config.set_storage_volume(self.__storage_volume.getSelection())
+ volume = self.get_libvirt().get_storage_volume(self.__config.get_storage_pool(),
+ self.__config.get_storage_volume())
+ self.__config.set_storage_size(volume.info()[1] / 1024.0 ** 3)
+ elif page is BRIDGE_PAGE:
+ self.__config.set_network_bridge(self.__network_bridges.getSelection())
+ elif page is VIRT_DETAILS_PAGE:
+ self.__config.set_virt_type(self.__virt_types.getSelection())
+ self.__config.set_architecture(self.__architectures.getSelection())
+ elif page is CONFIRM_PAGE:
+ self.get_libvirt().define_domain(self.__config, CreateMeter())
+ self.set_finished()
+
+ def get_back_page(self, page):
+ result = page
+ if page is OS_TYPE_PAGE:
+ install_type = self.__config.get_install_type()
+ if install_type == DomainConfig.LOCAL_INSTALL:
+ if self.__config.get_use_cdrom_source():
+ result = SELECT_CDROM_PAGE
+ else:
+ result = SELECT_ISO_PAGE
+ elif install_type == DomainConfig.NETWORK_INSTALL:
+ result = NETWORK_INSTALL_PAGE
+ elif install_type == DomainConfig.PXE_INSTALL:
+ result = VM_DETAILS_PAGE
+ elif page is LOCAL_STORAGE_PAGE or page is SELECT_VOLUME_PAGE:
+ result = ENABLE_STORAGE_PAGE
+ elif page is SELECT_POOL_PAGE:
+ result = ENABLE_STORAGE_PAGE
+ elif page is NETWORK_INSTALL_PAGE:
+ result = VM_DETAILS_PAGE
+ elif page is SELECT_CDROM_PAGE or page == SELECT_ISO_PAGE:
+ result = LOCAL_INSTALL_PAGE
+ elif page is BRIDGE_PAGE:
+ if self.__config.get_use_local_storage():
+ result = LOCAL_STORAGE_PAGE
+ else:
+ result = SELECT_VOLUME_PAGE
+ else:
+ if page > 1: result = page - 1
+ return result
+
+ def get_next_page(self, page):
+ result = page
+ if page is VM_DETAILS_PAGE:
+ install_type = self.__config.get_install_type()
+ if install_type == DomainConfig.LOCAL_INSTALL:
+ result = LOCAL_INSTALL_PAGE
+ elif install_type == DomainConfig.NETWORK_INSTALL:
+ result = NETWORK_INSTALL_PAGE
+ elif install_type == DomainConfig.PXE_INSTALL:
+ result = OS_TYPE_PAGE
+ elif page is LOCAL_INSTALL_PAGE:
+ if self.__config.get_use_cdrom_source():
+ result = SELECT_CDROM_PAGE
+ else:
+ result = SELECT_ISO_PAGE
+ elif page is SELECT_CDROM_PAGE or page == SELECT_ISO_PAGE:
+ result = OS_TYPE_PAGE
+ elif page is NETWORK_INSTALL_PAGE:
+ result = OS_TYPE_PAGE
+ elif page is ENABLE_STORAGE_PAGE:
+ result = BRIDGE_PAGE
+ if self.__config.get_enable_storage():
+ if self.__config.get_use_local_storage():
+ result = LOCAL_STORAGE_PAGE
+ else:
+ result = SELECT_POOL_PAGE
+ elif page is LOCAL_STORAGE_PAGE:
+ result = BRIDGE_PAGE
+ else:
+ result = page + 1
+ return result
+
+ def page_has_finish(self, page):
+ if page is CONFIRM_PAGE: return True
+ return False
+
+ def page_has_next(self, page):
+ if page is SELECT_POOL_PAGE: return self.__has_pools
+ elif page is SELECT_VOLUME_PAGE: return self.__has_volumes
+ elif page < CONFIRM_PAGE:
+ return True
+
+ def get_vm_details_page(self, screen):
+ self.__guest_name = Entry(50, self.__config.get_guest_name())
+ self.__install_type = RadioBar(screen, (("Local install media (ISO image or CDROM)",
+ DomainConfig.LOCAL_INSTALL,
+ self.__config.is_install_type(DomainConfig.LOCAL_INSTALL)),
+ ("Network Install (HTTP, FTP, or NFS)",
+ DomainConfig.NETWORK_INSTALL,
+ self.__config.is_install_type(DomainConfig.NETWORK_INSTALL)),
+ ("Network Boot (PXE)",
+ DomainConfig.PXE_INSTALL,
+ self.__config.is_install_type(DomainConfig.PXE_INSTALL))))
+ grid = Grid(2,3)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__guest_name, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Choose how you would like to install the operating system"), 1, 1,
+ anchorLeft = 1, anchorTop = 1)
+ grid.setField(self.__install_type, 1, 2, anchorLeft = 1)
+ return [Label("Enter your machine details"),
+ grid]
+
+ def get_local_install_page(self, screen):
+ self.__install_source = RadioBar(screen, (("Use CDROM or DVD",
+ DomainConfig.INSTALL_SOURCE_CDROM,
+ self.__config.get_use_cdrom_source()),
+ ("Use ISO image",
+ DomainConfig.INSTALL_SOURCE_ISO,
+ self.__config.get_use_cdrom_source() is False)))
+ grid = Grid(1,1)
+ grid.setField(self.__install_source, 0, 0, anchorLeft = 1)
+ return [Label("Locate your install media"),
+ grid]
+
+ def get_select_cdrom_page(self, screen):
+ drives = []
+ media = self.get_hal().list_installable_volumes()
+ for drive in media.keys():
+ drives.append([media[drive], drive, self.__config.is_install_media(drive)])
+ self.__install_media = RadioBar(screen, (drives))
+ grid = Grid(1, 1)
+ grid.setField(self.__install_media, 0, 0)
+ return [Label("Select the install media"),
+ grid]
+
+ def get_select_iso_page(self, screen):
+ self.__iso_path = Entry(50, self.__config.get_iso_path())
+ grid = Grid(1, 2)
+ grid.setField(Label("Enter ISO path:"), 0, 0, anchorLeft = 1)
+ grid.setField(self.__iso_path, 0, 1, anchorLeft = 1)
+ return [Label("Enter the full path to an install ISO"),
+ grid]
+
+ def get_network_install_page(self, screen):
+ self.__install_url = Entry(50, self.__config.get_install_url())
+ self.__kickstart_url = Entry(50, self.__config.get_kickstart_url())
+ self.__kernel_options = Entry(50, self.__config.get_kernel_options())
+ grid = Grid(2,3)
+ grid.setField(Label("URL:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__install_url, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Kickstart URL:"), 0, 1, anchorRight = 1)
+ grid.setField(self.__kickstart_url, 1, 1, anchorLeft = 1)
+ grid.setField(Label("Kernel Options:"), 0, 2, anchorRight = 1)
+ grid.setField(self.__kernel_options, 1, 2, anchorLeft = 1)
+ return [Label("Provide the operating system URL"),
+ grid]
+
+ def get_os_type_page(self, screen):
+ types = []
+ for type in Guest.list_os_types():
+ types.append([Guest.get_os_type_label(type), type, self.__config.is_os_type(type)])
+ self.__os_types = RadioBar(screen, types)
+ grid = Grid(1, 1)
+ grid.setField(self.__os_types, 0, 0, anchorLeft = 1)
+ return [Label("Choose the operating system type"),
+ grid]
+
+ def get_os_variant_page(self, screen):
+ variants = []
+ type = self.__config.get_os_type()
+ for variant in Guest.list_os_variants(type):
+ variants.append([Guest.get_os_variant_label(type, variant), variant, self.__config.is_os_variant(variant)])
+ self.__os_variants = RadioBar(screen, variants)
+ grid = Grid(1, 1)
+ grid.setField(self.__os_variants, 0, 0, anchorLeft = 1)
+ return [Label("Choose the operating system version"),
+ grid]
+
+ def get_ram_and_cpu_page(self, screen):
+ self.__memory = Entry(10, str(self.__config.get_memory()))
+ self.__cpus = Entry(10, str(self.__config.get_cpus()))
+ grid = Grid(2,2)
+ grid.setField(Label("Memory (RAM):"), 0, 0, anchorRight = 1)
+ grid.setField(self.__memory, 1, 0, anchorLeft = 1)
+ grid.setField(Label("CPUs:"), 0, 1, anchorRight = 1)
+ grid.setField(self.__cpus, 1, 1, anchorLeft = 1)
+ return [Label("Choose memory and CPU settings"),
+ grid]
+
+ def get_enable_storage_page(self, screen):
+ self.__enable_storage = Checkbox("Enable storage for this virtual machine", self.__config.get_enable_storage())
+ self.__storage_type = RadioBar(screen,((["Create a disk image on the computer's hard disk",
+ DomainConfig.NEW_STORAGE,
+ self.__config.get_use_local_storage()]),
+ (["Select managed or other existing storage",
+ DomainConfig.EXISTING_STORAGE,
+ self.__config.get_use_local_storage() is False])))
+ grid = Grid(1,2)
+ grid.setField(self.__enable_storage, 0, 0, anchorLeft = 1)
+ grid.setField(self.__storage_type, 0, 1, anchorLeft = 1)
+ return [Label("Configure storage"),
+ grid]
+
+ def get_local_storage_page(self, screen):
+ self.__storage_size = Entry(6, str(self.__config.get_storage_size()))
+ self.__allocate_storage = Checkbox("Allocate entire disk now", self.__config.get_allocate_storage())
+ grid = Grid(2, 2)
+ grid.setField(self.__allocate_storage, 0, 0, growx = 1, anchorLeft = 1)
+ grid.setField(Label("Storage size (GB):"), 0, 1, anchorLeft = 1)
+ grid.setField(self.__storage_size, 1, 1)
+ return [Label("Configure local storage"),
+ grid]
+
+ def get_select_pool_page(self, screen):
+ pools = []
+ for pool in self.get_libvirt().list_storage_pools():
+ pools.append([pool, pool, pool == self.__config.get_storage_pool()])
+ if len(pools) > 0:
+ self.__storage_pool = RadioBar(screen, (pools))
+ grid = Grid(2, 1)
+ grid.setField(Label("Storage pool:"), 0, 0, anchorTop = 1)
+ grid.setField(self.__storage_pool, 1, 0)
+ self.__has_pools = True
+ else:
+ grid = Label("There are no storage pools available.")
+ self.__has_pools = False
+ return [Label("Configure Managed Storage: Select A Pool"),
+ grid]
+
+ def get_select_volume_page(self, screen):
+ volumes = []
+ for volume in self.get_libvirt().list_storage_volumes(self.__config.get_storage_pool()):
+ volumes.append([volume, volume, volume == self.__config.get_storage_volume()])
+ if len(volumes) > 0:
+ self.__storage_volume = RadioBar(screen, (volumes))
+ grid = Grid(2, 1)
+ grid.setField(Label("Storage volumes:"), 0, 0, anchorTop = 1)
+ grid.setField(self.__storage_volume, 1, 0)
+ self.__has_volumes = True
+ else:
+ grid = Label("This storage pool has no defined volumes.")
+ self.__has_volumes = False
+ return [Label("Configure Managed Storage: Select A Volume"),
+ grid]
+
+ def get_bridge_page(self, screen):
+ bridges = []
+ for bridge in self.get_libvirt().list_bridges():
+ bridges.append(["Virtual network '%s'" % bridge.name(), bridge.name(), self.__config.get_network_bridge() is bridge.name()])
+ self.__network_bridges = RadioBar(screen, (bridges))
+ if self.__config.get_mac_address() is None:
+ self.__config.set_mac_address(self.get_libvirt().generate_mac_address())
+ self.__mac_address = Entry(20, self.__config.get_mac_address())
+ grid = Grid(1, 1)
+ grid.setField(self.__network_bridges, 0, 0)
+ return [Label("Select an existing bridge"),
+ grid]
+
+ def get_virt_details_page(self, screen):
+ virt_types = []
+ for type in self.get_libvirt().list_virt_types():
+ virt_types.append([type, type, self.__config.is_virt_type(type)])
+ self.__virt_types = RadioBar(screen, (virt_types))
+ archs = []
+ for arch in self.get_libvirt().list_architectures():
+ archs.append([arch, arch, self.__config.is_architecture(arch)])
+ self.__architectures = RadioBar(screen, (archs))
+ grid = Grid(2, 2)
+ grid.setField(Label("Virt Type:"), 0, 0, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__virt_types, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Architecture:"), 0, 1, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__architectures, 1, 1, anchorLeft = 1)
+ return [Label("Configure virtualization details"),
+ grid]
+
+ def get_confirm_page(self, screen):
+ grid = Grid(2, 6)
+ grid.setField(Label("OS:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(Guest.get_os_variant_label(self.__config.get_os_type(),
+ self.__config.get_os_variant())), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Install:"), 0, 1, anchorRight = 1)
+ grid.setField(Label(self.__config.get_install_type_text()), 1, 1, anchorLeft = 1)
+ grid.setField(Label("Memory:"), 0, 2, anchorRight = 1)
+ grid.setField(Label("%s MB" % self.__config.get_memory()), 1, 2, anchorLeft = 1)
+ grid.setField(Label("CPUs:"), 0, 3, anchorRight = 1)
+ grid.setField(Label("%d" % self.__config.get_cpus()), 1, 3, anchorLeft = 1)
+ grid.setField(Label("Storage:"), 0, 4, anchorRight = 1)
+ grid.setField(Label("%s (on %s)" % (self.__config.get_storage_volume(),
+ self.__config.get_storage_pool())),
+ 1, 4, anchorLeft = 1)
+ grid.setField(Label("Network:"), 0, 5, anchorRight = 1)
+ grid.setField(Label(self.__config.get_network_bridge()), 1, 5, anchorLeft = 1)
+ return [Label("Ready to begin installation of %s" % self.__config.get_guest_name()),
+ grid]
+
+def AddDomain():
+ screen = DomainConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/addhost.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/addhost.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,135 @@
+# addhost.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+from configscreen import *
+
+DETAILS_PAGE = 1
+CONFIRM_PAGE = 2
+
+HYPERVISOR_XEN = "xen"
+HYPERVISOR_KVM = "kvm"
+
+HYPERVISORS = {HYPERVISOR_XEN : "Xen",
+ HYPERVISOR_KVM : "QEMU/KVM"}
+
+CONNECTION_LOCAL = "local"
+CONNECTION_KERBEROS = "kerberos"
+CONNECTION_SSL = "ssl"
+CONNECTION_SSH = "ssh"
+
+CONNECTIONS = {CONNECTION_LOCAL : "Local",
+ CONNECTION_KERBEROS : "Remote Password or Kerberos",
+ CONNECTION_SSL : "Remote SSL/TLS with x509 certificate",
+ CONNECTION_SSH : "Remote tunnel over SSH"}
+
+class AddHostConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScreen.__init__(self, "Add A Remote Host")
+ self.__configured = False
+
+ def get_elements_for_page(self, screen, page):
+ if page is DETAILS_PAGE: return self.get_details_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ return page < CONFIRM_PAGE
+
+ def page_has_back(self, page):
+ return page > DETAILS_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def validate_input(self, page, errors):
+ if page is DETAILS_PAGE:
+ if self.__connection.getSelection() is CONNECTION_LOCAL:
+ return True
+ elif len(self.__hostname.value()) > 0:
+ return True
+ else:
+ errors.append("You must enter a remote hostname.")
+ elif page is CONFIRM_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is CONFIRM_PAGE:
+ hv = self.__hypervisor.getSelection()
+ conn = self.__connection.getSelection()
+ hostname = self.__hostname.value()
+
+ if hv is HYPERVISOR_XEN:
+ if conn is CONNECTION_LOCAL: url = "xen:///"
+ elif conn is CONNECTION_KERBEROS: url = "xen+tcp:///" + hostname + "/"
+ elif conn is CONNECTION_SSL: url = "xen+tls:///" + hostname + "/"
+ elif conn is CONNECTION_SSH: url = "xen+ssh:///" + hostname + "/"
+ elif hv is HYPERVISOR_KVM:
+ if conn is CONNECTION_LOCAL: url = "qemu:///system"
+ elif conn is CONNECTION_KERBEROS: url = "qemu+tcp://" + hostname + "/system"
+ elif conn is CONNECTION_SSL: url = "qemu+tls://" + hostname + "/system"
+ elif conn is CONNECTION_SSH: url = "qemu+ssh://" + hostname + "/system"
+
+ self.get_virt_manager_config().add_connection(url)
+ self.set_finished()
+
+ def get_details_page(self, screen):
+ if not self.__configured:
+ self.__hypervisor = RadioBar(screen, ((HYPERVISORS[HYPERVISOR_XEN], HYPERVISOR_XEN, True),
+ (HYPERVISORS[HYPERVISOR_KVM], HYPERVISOR_KVM, False)))
+ self.__connection = RadioBar(screen, ((CONNECTIONS[CONNECTION_LOCAL], CONNECTION_LOCAL, True),
+ (CONNECTIONS[CONNECTION_KERBEROS], CONNECTION_KERBEROS, False),
+ (CONNECTIONS[CONNECTION_SSL], CONNECTION_SSL, False),
+ (CONNECTIONS[CONNECTION_SSH], CONNECTION_SSH, False)))
+ self.__hostname = Entry(50, "")
+ self.__autoconnect = Checkbox("Autoconnect on Startup")
+ self.__configured = True
+ grid = Grid(2, 4)
+ grid.setField(Label("Hypervisor:"), 0, 0, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__hypervisor, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Connection:"), 0, 1, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__connection, 1, 1, anchorLeft = 1)
+ grid.setField(Label("Hostname:"), 0, 2, anchorRight = 1)
+ grid.setField(self.__hostname, 1, 2, anchorLeft = 1)
+ grid.setField(Label(""), 0, 3, anchorRight = 1)
+ grid.setField(self.__autoconnect, 1, 3, anchorLeft = 1)
+ return [Label("Add Connection"),
+ grid]
+
+ def get_confirm_page(self, screen):
+ grid = Grid(2, 4)
+ grid.setField(Label("Hypervisor:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(HYPERVISORS[self.__hypervisor.getSelection()]), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Connection:"), 0, 1, anchorRight = 1)
+ grid.setField(Label(CONNECTIONS[self.__connection.getSelection()]), 1, 1, anchorLeft = 1)
+ if self.__connection.getSelection() is not CONNECTION_LOCAL:
+ hostname = self.__hostname.value()
+ else:
+ hostname = "local"
+ grid.setField(Label("Hostname:"), 0, 2, anchorRight = 1)
+ grid.setField(Label(hostname), 1, 2, anchorLeft = 1)
+ grid.setField(Label("Autoconnect on Startup:"), 0, 3, anchorRight = 1)
+ label = "Yes"
+ if not self.__autoconnect.value(): label = "No"
+ grid.setField(Label(label), 1, 3, anchorLeft = 1)
+ return [Label("Confirm Connection"),
+ grid]
+
+def AddHost():
+ screen = AddHostConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/addpool.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/addpool.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,187 @@
+# addstorage.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+import utils
+
+from configscreen import *
+from poolconfig import PoolConfig
+from virtinst import Storage
+
+POOL_NAME_PAGE = 1
+POOL_DETAILS_PAGE = 2
+CONFIRM_PAGE = 3
+
+class AddStoragePoolConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScreen.__init__(self, "Add A Storage Pool")
+ self.__config = PoolConfig(self.get_libvirt())
+
+ def get_elements_for_page(self, screen, page):
+ if page is POOL_NAME_PAGE: return self.get_pool_name_page(screen)
+ elif page is POOL_DETAILS_PAGE: return self.get_pool_details_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ return page < CONFIRM_PAGE
+
+ def page_has_back(self, page):
+ return page > POOL_NAME_PAGE
+
+ return page > POOL_NAME_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def validate_input(self, page, errors):
+ if page is POOL_NAME_PAGE:
+ if utils.string_is_not_blank(self.__name.value()):
+ if self.get_libvirt().storage_pool_exists(self.__name.value()):
+ errors.append("Name '%s' already in use by another pool." % self.__name.value())
+ else:
+ return True
+ else:
+ errors.append("Storage object name must be a string between 0 and 50 characters.")
+ elif page is POOL_DETAILS_PAGE:
+ result = True
+ if self.__config.needs_target_path():
+ if utils.string_is_not_blank(self.__target_path.value()):
+ if self.__target_path.value()[0:1] is not '/':
+ errors.append("'%s' is not an absolute path." % self.__target_path.value())
+ result = False
+ else:
+ errors.append("You must enter a target path.")
+ result = False
+ if self.__config.needs_format():
+ if self.__formats.getSelection() is None:
+ errors.append("You must select a pool format.")
+ result = False
+ if self.__config.needs_hostname():
+ if not utils.string_is_not_blank(self.__hostname.value()):
+ errors.append("You must enter a hostname.")
+ result = False
+ if self.__config.needs_source_path():
+ if utils.string_is_not_blank(self.__source_path.value()):
+ if self.__config.source_must_be_absolute():
+ if self.__source_path.value()[0:1] is not '/':
+ errors.append("'%s' is not an absolute path." % self.__source_path.value())
+ result = False
+ else:
+ errors.append("you must enter a source path.")
+ result = False
+ return result
+ elif page is CONFIRM_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is POOL_NAME_PAGE:
+ self.__config.set_name(self.__name.value())
+ self.__config.set_type(self.__type.getSelection())
+ #self._reset_flags(self.__type.current())
+ elif page is POOL_DETAILS_PAGE:
+ if self.__config.needs_target_path():
+ self.__config.set_target_path(self.__target_path.value())
+ if self.__config.needs_format():
+ self.__config.set_format(self.__formats.getSelection())
+ if self.__config.needs_hostname():
+ self.__config.set_hostname(self.__hostname.value())
+ if self.__config.needs_source_path():
+ self.__config.set_source_path(self.__source_path.value())
+ if self.__config.needs_build_pool():
+ self.__config.set_build_pool(self.__build_pool.value())
+ elif page is CONFIRM_PAGE:
+ self.get_libvirt().define_storage_pool(self.__config.get_name(), config = self.__config)
+ self.get_libvirt().create_storage_pool(self.__config.get_name())
+ self.set_finished()
+
+ def get_pool_name_page(self, screen):
+ self.__name = Entry(50, self.__config.get_name())
+ pooltypes = []
+ for pooltype in Storage.StoragePool.get_pool_types():
+ pooltypes.append(["%s: %s" % (pooltype, Storage.StoragePool.get_pool_type_desc(pooltype)),
+ pooltype,
+ self.__config.get_type() is pooltype])
+ self.__type = RadioBar(screen, pooltypes)
+ grid = Grid(2, 2)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__name, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Type:"), 0, 1, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__type, 1, 1, anchorLeft = 1)
+ return [Label("Add Storage Pool"),
+ grid]
+
+ def get_pool_details_page(self, screen):
+ rows = 0
+ if self.__config.needs_target_path():
+ self.__target_path = Entry(50, self.__config.get_target_path())
+ rows += 1
+ if self.__config.needs_format():
+ formats = []
+ for format in self.__config.get_formats():
+ formats.append([format, format, format is self.__config.get_format()])
+ self.__formats = RadioBar(screen, formats)
+ rows += 1
+ if self.__config.needs_hostname():
+ self.__hostname = Entry(50, self.__config.get_hostname())
+ rows += 1
+ if self.__config.needs_source_path():
+ self.__source_path = Entry(50, self.__config.get_source_path())
+ rows += 1
+ if self.__config.needs_build_pool():
+ self.__build_pool = Checkbox("Build Pool", self.__config.get_build_pool())
+ rows += 1
+ self.__build_pool = Checkbox("Build Pool", self.__config.get_build_pool())
+ rows += 1
+ grid = Grid(2, rows)
+ currentrow = 0
+ if self.__config.needs_target_path():
+ grid.setField(Label("Target Path:"), 0, currentrow, anchorRight = 1)
+ grid.setField(self.__target_path, 1, currentrow, anchorLeft = 1)
+ currentrow += 1
+ if self.__config.needs_format():
+ grid.setField(Label("Format:"), 0, currentrow, anchorRight = 1, anchorTop = 1)
+ grid.setField(self.__formats, 1, currentrow, anchorLeft = 1)
+ currentrow += 1
+ if self.__config.needs_hostname():
+ grid.setField(Label("Host Name:"), 0, currentrow, anchorRight = 1)
+ grid.setField(self.__hostname, 1, currentrow, anchorRight = 1)
+ currentrow += 1
+ if self.__config.needs_source_path():
+ grid.setField(Label("Source Path:"), 0, currentrow, anchorRight = 1)
+ grid.setField(self.__source_path, 1, currentrow, anchorLeft = 1)
+ currentrow += 1
+ if self.__config.needs_build_pool():
+ grid.setField(Label(" "), 0, currentrow, anchorRight = 1)
+ grid.setField(self.__build_pool, 1, currentrow, anchorLeft = 1)
+ currentrow += 1
+ return [Label("Specify a storage location to be later split into virtual machine storage"),
+ grid]
+
+ def get_confirm_page(self, screen):
+ grid = Grid(2, 2)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(self.__config.get_name()), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Target Path:"), 0, 1, anchorRight = 1)
+ grid.setField(Label(self.__config.get_target_path()), 1, 1, anchorLeft = 1)
+ return [Label("Confirm Pool Details"),
+ grid]
+
+def AddStoragePool():
+ screen = AddStoragePoolConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/addvolume.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/addvolume.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,178 @@
+# addvolume.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from createmeter import CreateMeter
+from configscreen import *
+from volumeconfig import StorageVolumeConfig
+from utils import *
+
+SELECT_POOL_PAGE = 1
+VOLUME_NAME_PAGE = 2
+VOLUME_FORMAT_PAGE = 3
+MAX_CAPACITY_PAGE = 4
+CONFIRM_PAGE = 5
+
+class AddVolumeConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "Add A New Storage Volume")
+ self.__config = StorageVolumeConfig()
+
+ def get_elements_for_page(self, screen, page):
+ if page is SELECT_POOL_PAGE: return self.get_storage_pool_list_page(screen)
+ elif page is VOLUME_NAME_PAGE: return self.get_volume_name_page(screen)
+ elif page is VOLUME_FORMAT_PAGE: return self.get_volume_format_page(screen)
+ elif page is MAX_CAPACITY_PAGE: return self.get_max_capacity_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ if page is SELECT_POOL_PAGE:
+ return self.has_selectable_pools()
+ else:
+ if page < CONFIRM_PAGE: return True
+ return False
+
+ def page_has_back(self, page):
+ if page > SELECT_POOL_PAGE: return True
+ return False
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def get_next_page(self, page):
+ if page is VOLUME_NAME_PAGE:
+ if self.__config.needs_format():
+ return VOLUME_FORMAT_PAGE
+ else:
+ return MAX_CAPACITY_PAGE
+ return StorageListConfigScreen.get_next_page(self, page)
+
+ def get_back_page(self, page):
+ if page is MAX_CAPACITY_PAGE:
+ if self.__config.needs_format():
+ return VOLUME_FORMAT_PATH
+ else:
+ return VOLUME_NAME_PAGE
+ return StorageListConfigScreen.get_back_page(self, page)
+
+ def validate_input(self, page, errors):
+ if page is SELECT_POOL_PAGE:
+ if self.get_selected_pool() is not None:
+ return True
+ else:
+ errors.append("You must select a storage pool.")
+ elif page is VOLUME_NAME_PAGE:
+ if string_is_not_blank(self.__name.value()):
+ return True
+ else:
+ errors.append("Storage object name can only contain alphanumeric, '_', '.', or '-' characters.")
+ elif page is VOLUME_FORMAT_PAGE:
+ if self.__formats.current() is not None:
+ return True
+ else:
+ errors.append("You must select a volume format.")
+ elif page is MAX_CAPACITY_PAGE:
+ if string_is_not_blank(self.__capacity.value()):
+ if string_is_not_blank(self.__allocation.value()):
+ capacity = int(self.__capacity.value())
+ allocation = int(self.__allocation.value())
+ if capacity > 0:
+ if capacity <= self.__config.get_pool().info()[3] / 1024**2:
+ if allocation >= 0:
+ if allocation <= capacity:
+ return True
+ else:
+ errors.append("Allocation cannot exceed the maximum capacity.")
+ else:
+ errors.append("The allocation must be greater than or equal to 0.")
+ else:
+ errors.append("The maximum capacity cannot exceed the storage pool size.")
+ else:
+ errors.append("The capacity must be greater than zero.")
+ else:
+ errors.append("An allocation value must be entered.")
+ else:
+ errors.append("A maximum volume capacity must be entered.")
+ elif page is CONFIRM_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is SELECT_POOL_PAGE:
+ self.__config.set_pool(self.get_libvirt().get_storage_pool(self.get_selected_pool()))
+ elif page is VOLUME_NAME_PAGE:
+ self.__config.set_name(self.__name.value())
+ elif page is VOLUME_FORMAT_PAGE:
+ self.__config.set_format(self.__formats.current())
+ elif page is MAX_CAPACITY_PAGE:
+ self.__config.set_max_capacity(int(self.__capacity.value()))
+ self.__config.set_allocation(int(self.__allocation.value()))
+ elif page is CONFIRM_PAGE:
+ self.get_libvirt().define_storage_volume(self.__config, CreateMeter())
+ self.set_finished()
+
+ def get_volume_name_page(self, screen):
+ self.__name = Entry(50, self.__config.get_name())
+ grid = Grid(2, 1)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__name, 1, 0, anchorLeft = 1)
+ return [Label("New Storage Volume"),
+ grid,
+ Label("Name of the volume to create. File extension may be appended.")]
+
+ def get_volume_format_page(self, screen):
+ self.__formats = Listbox(0)
+ for format in self.__config.get_formats_for_pool():
+ self.__formats.append(format, format)
+ grid = Grid(1, 1)
+ grid.setField(self.__formats, 0, 0)
+ return [Label("Select The Volume Format"),
+ grid]
+
+ def get_max_capacity_page(self, screen):
+ self.__capacity = Entry(6, str(self.__config.get_max_capacity()))
+ self.__allocation = Entry(6, str(self.__config.get_allocation()))
+ grid = Grid(2, 2)
+ grid.setField(Label("Max. Capacity (MB):"), 0, 0, anchorRight = 1)
+ grid.setField(self.__capacity, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Allocation (MB):"), 0, 1, anchorRight = 1)
+ grid.setField(self.__allocation, 1, 1, anchorLeft = 1)
+ return [Label("Storage Volume Quota"),
+ Label("%s's available space: %s" % (self.__config.get_pool().name(),
+ size_as_mb_or_gb(self.__config.get_pool().info()[3]))),
+ grid]
+
+ def get_confirm_page(self, screen):
+ grid = Grid(2, 5)
+ grid.setField(Label("Volume Name:"), 0, 0, anchorRight = 1)
+ grid.setField(Label("%s (%s)" % (self.__config.get_name(), self.__config.get_pool().name())), 1, 0, anchorLeft = 1)
+ if self.__config.needs_format():
+ grid.setField(Label("Format:"), 0, 1, anchorRight = 1)
+ grid.setField(Label(self.__config.get_format()), 1, 1, anchorLeft = 1)
+ # NOTE: here we multiply the sizes by 1024^2 since the size_as_mb_or_gb is expect bytes
+ grid.setField(Label("Max. Capacity:"), 0, 2, anchorRight = 1)
+ grid.setField(Label("%s" % (size_as_mb_or_gb(self.__config.get_max_capacity() * 1024**2))), 1, 2, anchorLeft = 1)
+ grid.setField(Label("Allocation:"), 0, 3, anchorRight = 1)
+ grid.setField(Label("%s" % (size_as_mb_or_gb(self.__config.get_allocation() * 1024**2))), 1, 3, anchorLeft = 1)
+ return [Label("Ready To Allocation New Storage Volume"),
+ grid]
+
+def AddStorageVolume():
+ screen = AddVolumeConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/changehost.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/changehost.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,60 @@
+# changehost.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+import logging
+import libvirtworker
+from configscreen import *
+
+CONNECTION_LIST_PAGE = 1
+CONNECTED_PAGE = 2
+
+class ChangeHostConfigScreen(HostListConfigScreen):
+ def __init__(self):
+ HostListConfigScreen.__init__(self, "")
+
+ def get_title(self):
+ return "Currently: %s" % self.get_libvirt().get_url()
+
+ def get_elements_for_page(self, screen, page):
+ if page is CONNECTION_LIST_PAGE: return self.get_connection_list_page(screen)
+ elif page is CONNECTED_PAGE: return self.get_connected_page(screen)
+
+ def process_input(self, page):
+ if page is CONNECTION_LIST_PAGE:
+ logging.info("Changing libvirt connection to %s" % self.get_selected_connection())
+ self.get_libvirt().open_connection(self.get_selected_connection())
+ elif page is CONNECTED_PAGE: self.set_finished()
+
+ def page_has_next(self, page):
+ if page is CONNECTION_LIST_PAGE: return self.has_selectable_connections()
+ return False
+
+ def page_has_back(self, page):
+ return page > CONNECTION_LIST_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONNECTED_PAGE
+
+ def get_connected_page(self, screen):
+ return [Label("Connected to %s" % self.get_selected_connection())]
+
+def ChangeHost():
+ screen = ChangeHostConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/configscreen.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/configscreen.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,295 @@
+# configscreen.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from halworker import HALWorker
+from libvirtworker import *
+import traceback
+
+BACK_BUTTON = "back"
+NEXT_BUTTON = "next"
+CANCEL_BUTTON = "cancel"
+FINISH_BUTTON = "finish"
+
+class ConfigScreen:
+ '''Enables the creation of navigable, multi-paged configuration screens.'''
+
+ def __init__(self, title):
+ self.__title = title
+ self.__current_page = 1
+ self.__finished = False
+ self.__hal = HALWorker()
+ self.__libvirt = LibvirtWorker()
+ self.__vm_config = VirtManagerConfig()
+
+ def get_title(self):
+ return self.__title
+
+ def get_hal(self):
+ return self.__hal
+
+ def get_libvirt(self):
+ return self.__libvirt
+
+ def get_virt_manager_config(self):
+ return self.__vm_config
+
+ def set_finished(self):
+ self.__finished = True
+
+ def get_elements_for_page(self, screen, page):
+ return []
+
+ def page_has_next(self, page):
+ return False
+
+ def page_has_finish(self, page):
+ return False
+
+ def get_back_page(self, page):
+ if page > 1: return page - 1
+ return page
+
+ def go_back(self):
+ self.__current_page = self.get_back_page(self.__current_page)
+
+ def get_next_page(self, page):
+ return page + 1
+
+ def go_next(self):
+ self.__current_page = self.get_next_page(self.__current_page)
+
+ def validate_input(self, page, errors):
+ return True
+
+ def process_input(self, page):
+ return
+
+ def get_page_list(self):
+ return []
+
+ def get_current_page(self):
+ 0
+
+ def start(self):
+ active = True
+ while active and (self.__finished == False):
+ screen = SnackScreen()
+ elements = self.get_elements_for_page(screen, self.__current_page)
+ # TODO: need to set the form height to the number of elements on the page
+ gridform = GridForm(screen, self.get_title(), 2, 2)
+
+ # Here you would put the list of elements
+ # and programmatically set the indicator as
+ # they're rendered
+ pages = self.get_page_list()
+ if len(pages) > 0:
+ leftmenu = Grid(2, len(pages))
+ current_element = 0
+ for page in pages:
+ leftmenu.setField(Label(page), 0, current_element, anchorLeft = 1)
+ indicator = " "
+ if current_element == self.__current_page - 1:
+ indicator = "<-"
+ leftmenu.setField(Label(indicator), 1, current_element)
+ current_element += 1
+ gridform.add(leftmenu, 0, 0, anchorTop = 1, padding = (3, 0, 3, 0))
+
+ content = Grid(1, len(elements) + 1)
+ current_element = 0
+ for element in elements:
+ content.setField(element, 0, current_element)
+ current_element += 1
+ # create the navigation buttons
+ buttons = []
+ if self.__current_page > 1: buttons.append(["Back", BACK_BUTTON, "F11"])
+ if self.page_has_next(self.__current_page): buttons.append(["Next", NEXT_BUTTON, "F12"])
+ if self.page_has_finish(self.__current_page): buttons.append(["Finish", FINISH_BUTTON, "F10"])
+ buttons.append(["Cancel", CANCEL_BUTTON, "ESC"])
+ buttonbar = ButtonBar(screen, buttons)
+ content.setField(buttonbar, 0, current_element, growx = 1)
+ gridform.add(content, 1, 0, anchorTop = 1)
+ current_element += 1
+ try:
+ result = gridform.runOnce()
+ pressed = buttonbar.buttonPressed(result)
+ if pressed == BACK_BUTTON:
+ self.go_back()
+ elif pressed == NEXT_BUTTON or pressed == FINISH_BUTTON:
+ errors = []
+ if self.validate_input(self.__current_page, errors):
+ self.process_input(self.__current_page)
+ self.go_next()
+ else:
+ error_text = ""
+ for error in errors:
+ error_text += "%s\n" % error
+ ButtonChoiceWindow(screen,
+ "There Were Errors",
+ error_text,
+ buttons = ["OK"])
+ elif pressed == CANCEL_BUTTON:
+ active = False
+ except Exception, error:
+ ButtonChoiceWindow(screen,
+ "An Exception Has Occurred",
+ str(error) + "\n" + traceback.format_exc(),
+ buttons = ["OK"])
+ screen.popWindow()
+ screen.finish()
+
+class DomainListConfigScreen(ConfigScreen):
+ '''Provides a base class for all config screens that require a domain list.'''
+
+ def __init__(self, title):
+ ConfigScreen.__init__(self, title)
+
+ def get_domain_list_page(self, screen, defined=True, created=True):
+ domains = self.get_libvirt().list_domains(defined, created)
+ result = None
+
+ if len(domains) > 0:
+ self.__has_domains = True
+ self.__domain_list = Listbox(0)
+ for name in domains:
+ self.__domain_list.append(name, name)
+ result = [self.__domain_list]
+ else:
+ self.__has_domains = False
+ grid = Grid(1, 1)
+ grid.setField(Label("There are no domains available."), 0, 0)
+ result = [grid]
+ return result
+
+ def get_selected_domain(self):
+ return self.__domain_list.current()
+
+ def has_selectable_domains(self):
+ return self.__has_domains
+
+class NetworkListConfigScreen(ConfigScreen):
+ '''Provides a base class for all config screens that require a network list.'''
+
+ def __init__(self, title):
+ ConfigScreen.__init__(self, title)
+
+ def get_network_list_page(self, screen, defined=True, created=True):
+ networks = self.get_libvirt().list_networks(defined, created)
+ result = None
+
+ if len(networks) > 0:
+ self.__has_networks = True
+ self.__network_list = Listbox(0)
+ for name in networks:
+ self.__network_list.append(name, name)
+ result = self.__network_list
+ else:
+ self.__has_networks = False
+ result = Label("There are no networks available.")
+ grid = Grid(1, 1)
+ grid.setField(result, 0, 0)
+ return [Label("Network List"),
+ grid]
+
+ def get_selected_network(self):
+ return self.__network_list.current()
+
+ def has_selectable_networks(self):
+ return self.__has_networks
+
+class StorageListConfigScreen(ConfigScreen):
+ '''Provides a base class for any configuration screen that deals with storage pool lists.'''
+
+ def __init__(self, title):
+ ConfigScreen.__init__(self, title)
+
+ def get_storage_pool_list_page(self, screen, defined=True, created=True):
+ pools = self.get_libvirt().list_storage_pools(defined=defined, created=created)
+ if len(pools) > 0:
+ self.__has_pools = True
+ self.__pools_list = Listbox(0)
+ for pool in pools:
+ self.__pools_list.append(pool, pool)
+ result = self.__pools_list
+ else:
+ self.__has_pools = False
+ result = Label("There are no storage pools available.")
+ grid = Grid(1, 1)
+ grid.setField(result, 0, 0)
+ return [Label("Storage Pool List"),
+ grid]
+
+ def get_selected_pool(self):
+ return self.__pools_list.current()
+
+ def has_selectable_pools(self):
+ return self.__has_pools
+
+ def get_storage_volume_list_page(self, screen):
+ '''Requires that self.__pools_list have a selected element.'''
+ pool = self.get_libvirt().get_storage_pool(self.get_selected_pool())
+ if len(pool.listVolumes()) > 0:
+ self.__has_volumes = True
+ self.__volumes_list = Listbox(0)
+ for volname in pool.listVolumes():
+ volume = pool.storageVolLookupByName(volname)
+ self.__volumes_list.append("%s (%0.2f GB)" % (volume.name(), volume.info()[2] / 1024**3), volume.name())
+ result = self.__volumes_list
+ else:
+ self.__has_volumes = False
+ result = Label("There are no storage volumes available.")
+ grid = Grid(1, 1)
+ grid.setField(result, 0, 0)
+ return [Label("Storage Volume List"),
+ grid]
+
+ def get_selected_volume(self):
+ return self.__volumes_list.current()
+
+ def has_selectable_volumes(self):
+ return self.__has_volumes
+
+class HostListConfigScreen(ConfigScreen):
+ '''Provides a base class for working with lists of libvirt hosts.'''
+
+ def __init__(self, title):
+ ConfigScreen.__init__(self, title)
+
+ def get_connection_list_page(self, screen):
+ connections = self.get_virt_manager_config().get_connection_list()
+ result = None
+
+ if len(connections) > 0:
+ self.__has_connections = True
+ self.__connection_list = Listbox(0)
+ for connection in connections:
+ self.__connection_list.append(connection, connection)
+ result = self.__connection_list
+ else:
+ self.__has_connections = False
+ result = Label("There are no defined connections.")
+ grid = Grid(1, 1)
+ grid.setField(result, 0, 0)
+ return [Label("Host List"),
+ grid]
+
+ def get_selected_connection(self):
+ return self.__connection_list.current()
+
+ def has_selectable_connections(self):
+ return self.__has_connections
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/createmeter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/createmeter.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,30 @@
+# createmeter.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import urlgrabber.progress as progress
+import logging
+
+class CreateMeter(progress.BaseMeter):
+ def _do_start(self, now = None):
+ logging.info("Starting...")
+
+ def _do_end(self, amount_read, now = None):
+ logging.info("Ending: read=%d" % amount_read)
+
+ def _do_update(self, amount_read, now = None):
+ logging.info("Update: read=%d" % amount_read)
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/createnetwork.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/createnetwork.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+#
+# createnetwork.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_PAGE = 1
+CREATE_PAGE = 2
+
+class CreateNetworkConfigScreen(NetworkListConfigScreen):
+ def __init__(self):
+ NetworkListConfigScreen.__init__(self, "Create A Network")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_PAGE: return self.get_network_list_page(screen, created = False)
+ elif page is CREATE_PAGE: return self.get_create_network_page(screen)
+
+ def page_has_next(self, page):
+ if page is LIST_PAGE: return self.has_selectable_networks()
+
+ def page_has_back(self, page):
+ return (page is CREATE_PAGE)
+
+ def validate_input(self, page, errors):
+ if page is LIST_PAGE:
+ self.get_libvirt().create_network(self.get_selected_network())
+ return True
+
+ def get_create_network_page(self, screen):
+ return [Label("Network Started"),
+ Label("%s was successfully started." % self.get_selected_network())]
+
+def CreateNetwork():
+ screen = CreateNetworkConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/createuser.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/createuser.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+#
+# createuser.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import ConfigScreen
+from userworker import UserWorker
+
+import libuser
+
+DETAILS_PAGE = 1
+CONFIRM_PAGE = 2
+
+class CreateUserConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScreen.__init__(self, "Create A User Account")
+ self.__username = None
+ self.__useradmin = libuser.admin()
+ self.__user_worker = UserWorker()
+
+ def get_elements_for_page(self, screen, page):
+ if page is DETAILS_PAGE: return self.get_details_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def validate_input(self, page, errors):
+ if page is DETAILS_PAGE:
+ if len(self.__username.value()) > 0:
+ name = self.__username.value()
+ if self.__useradmin.lookupUserByName(name) is None:
+ if len(self.__password.value()) > 0:
+ if self.__password.value() == self.__confirm.value():
+ return True
+ else:
+ errors.append("Passwords do not match.")
+ else:
+ errors.append("You must enter a password.")
+ else:
+ errors.append("User %s already exists." % name)
+ else:
+ errors.append("You must enter a username.")
+ self.__confirm.value()
+ return False
+
+ def process_input(self, page):
+ if page is CONFIRM_PAGE:
+ self.__user_worker.create_user(self.__username.value(),
+ self.__password.value(),
+ "wheel" if self.__adminuser.value() else None)
+ self.set_finished()
+
+ def page_has_next(self, page):
+ return (page is DETAILS_PAGE)
+
+ def page_has_back(self, page):
+ return (page is CONFIRM_PAGE)
+
+ def page_has_finish(self, page):
+ return (page is CONFIRM_PAGE)
+
+ def get_details_page(self, screen):
+ if self.__username is None:
+ self.__username = Entry(50, "")
+ self.__password = Entry(50, "", password = 1)
+ self.__confirm = Entry(50, "", password = 1)
+ self.__adminuser = Checkbox("This user is an administrator", False)
+ grid = Grid(2, 4)
+ grid.setField(Label("Username:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__username, 1, 0, anchorLeft = 1)
+ grid.setField(Label("Password:"), 0, 1, anchorRight = 1)
+ grid.setField(self.__password, 1, 1, anchorLeft = 1)
+ grid.setField(Label("Confirm password:"), 0, 2, anchorRight = 1)
+ grid.setField(self.__confirm, 1, 2, anchorLeft = 1)
+ grid.setField(Label(" "), 0, 3)
+ grid.setField(self.__adminuser, 1, 3, anchorLeft = 1)
+ return [Label("Enter The User Details"),
+ grid]
+
+ def get_confirm_page(self, screen):
+ grid = Grid(1, 2)
+ grid.setField(Label("Username: %s" % self.__username.value()), 0, 0)
+ admin_label = "is not"
+ if self.__adminuser.value():
+ admin_label = "is"
+ grid.setField(Label("This user %s an administrator." % admin_label), 0, 1)
+ return [Label("Create this user account?"),
+ grid]
+
+def CreateUser():
+ screen = CreateUserConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/definenet.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/definenet.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,257 @@
+# definenet.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from IPy import IP
+import traceback
+import logging
+import re
+
+from configscreen import ConfigScreen
+from networkconfig import NetworkConfig
+from utils import *
+
+NETWORK_NAME_PAGE = 1
+IPV4_ADDRESS_PAGE = 2
+PUBLIC_NETWORK_ALERT_PAGE = 3
+NETWORK_DETAILS_PAGE = 4
+DHCP_RANGE_PAGE = 5
+NETWORK_TYPE_PAGE = 6
+SELECT_PHYSICAL_NETWORK_PAGE = 7
+SUMMARY_PAGE = 8
+
+class DefineNetworkConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScreen.__init__(self, "Create A Virtual Network Interface")
+ self.__config = NetworkConfig()
+
+ def get_elements_for_page(self, screen, page):
+ if page is NETWORK_NAME_PAGE: return self.get_network_name_page(screen)
+ elif page is IPV4_ADDRESS_PAGE: return self.get_ipv4_address_page(screen)
+ elif page is PUBLIC_NETWORK_ALERT_PAGE: return self.get_public_network_alert_page(screen)
+ elif page is NETWORK_DETAILS_PAGE: return self.get_network_details_page(screen)
+ elif page is DHCP_RANGE_PAGE: return self.get_dhcp_range_page(screen)
+ elif page is NETWORK_TYPE_PAGE: return self.get_network_type_page(screen)
+ elif page is SELECT_PHYSICAL_NETWORK_PAGE: return self.get_select_physical_network_page(screen)
+ elif page is SUMMARY_PAGE: return self.get_summary_page(screen)
+
+ def validate_input(self, page, errors):
+ if page is NETWORK_NAME_PAGE:
+ if len(self.__name.value()) > 0:
+ if re.match("^[a-zA-Z0-9_]*$", self.__name.value()):
+ return True
+ else:
+ errors.append("The network name can only contain letters, numbers and the underscore, and no spaces.")
+ else:
+ errors.append("Network name must be non-blank and less than 50 characters")
+ elif page is IPV4_ADDRESS_PAGE:
+ if len(self.__ipv4_address.value()) > 0:
+ try:
+ self.__config.set_ipv4_address(self.__ipv4_address.value())
+ return True
+ except Exception, error:
+ errors.append("The network address could not be understood: %s" % str(error))
+ else:
+ errors.append("Network must be entered in the format 1.2.3.4/8")
+ elif page is PUBLIC_NETWORK_ALERT_PAGE: return True
+ elif page is NETWORK_DETAILS_PAGE: return True
+ elif page is DHCP_RANGE_PAGE:
+ try:
+ if len(self.__start_address.value()) > 0 and len(self.__end_address.value()) > 0:
+ start = IP(self.__start_address.value(), )
+ end = IP(self.__end_address.value())
+ if not self.__config.is_bad_address(start) and not self.__config.is_bad_address(end):
+ return True
+ else:
+ errors.append("Start and/or end address are outside of the choosen network.")
+ else:
+ errors.append("Start and end address must be non-blank.")
+ except Exception, error:
+ logging.error(str(error))
+ errors.append("The start and/or end addresses could not be understood.")
+ elif page is NETWORK_TYPE_PAGE: return True
+ elif page is SELECT_PHYSICAL_NETWORK_PAGE: return True
+ elif page is SUMMARY_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is NETWORK_NAME_PAGE:
+ self.__config.set_name(self.__name.value())
+ elif page is DHCP_RANGE_PAGE:
+ self.__config.set_ipv4_start_address(self.__start_address.value())
+ self.__config.set_ipv4_end_address(self.__end_address.value())
+ elif page is NETWORK_TYPE_PAGE:
+ self.__config.set_isolated_network(self.__isolated_network.value())
+ elif page is SELECT_PHYSICAL_NETWORK_PAGE:
+ self.__config.set_physical_device(self.__physical_devices.getSelection())
+ elif page is SUMMARY_PAGE:
+ self.get_libvirt().define_network(self.__config)
+ self.set_finished()
+
+ def get_next_page(self, page):
+ if page is IPV4_ADDRESS_PAGE:
+ if self.__config.is_public_ipv4_network():
+ return PUBLIC_NETWORK_ALERT_PAGE
+ else:
+ return NETWORK_DETAILS_PAGE
+ if page is NETWORK_TYPE_PAGE:
+ if self.__config.is_isolated_network():
+ return SUMMARY_PAGE
+ else:
+ return SELECT_PHYSICAL_NETWORK_PAGE
+ return ConfigScreen.get_next_page(self, page)
+
+ def get_back_page(self, page):
+ if page is NETWORK_DETAILS_PAGE:
+ return IPV4_ADDRESS_PAGE
+ if page is SUMMARY_PAGE:
+ if self.__config.is_isolated_network():
+ return NETWORK_TYPE_PAGE
+ else:
+ return SELECT_PHYSICAL_NETWORK_PAGE
+ return ConfigScreen.get_back_page(self, page)
+
+ def page_has_finish(self, page):
+ if page is SUMMARY_PAGE: return True
+ return False
+
+ def page_has_next(self, page):
+ if page < SUMMARY_PAGE: return True
+
+ def page_has_back(self, page):
+ if page > NETWORK_NAME_PAGE: return True
+ return False
+
+ def get_network_name_page(self, screen):
+ self.__name = Entry(50, self.__config.get_name())
+ grid = Grid(2, 1)
+ grid.setField(Label("Network Name:"), 0, 0)
+ grid.setField(self.__name, 1, 0)
+ return [Label("Please choose a name for your virtual network"),
+ grid]
+
+ def get_ipv4_address_page(self, screen):
+ self.__ipv4_address = Entry(18, self.__config.get_ipv4_address())
+ grid = Grid(2, 1)
+ grid.setField(Label("Network:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__ipv4_address, 1, 0, anchorLeft = 1)
+ return [Label("You will need to choose an IPv4 address space for the virtual network:"),
+ grid,
+ Label("HINT: The network should be chosen from"),
+ Label("one of the IPv4 private address ranges;"),
+ Label("e.g., 10.0.0.0/8, 172.168.0.0/12, 192.168.0.0/16")]
+
+ def get_network_details_page(self, screen):
+ grid = Grid(2, 6)
+ grid.setField(Label("Network:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(self.__config.get_ipv4_address()), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Netmask:"), 0, 1, anchorRight = 1)
+ grid.setField(Label(self.__config.get_ipv4_netmask()), 1, 1, anchorLeft = 1)
+ grid.setField(Label("Broadcast:"), 0, 2, anchorRight = 1)
+ grid.setField(Label(self.__config.get_ipv4_broadcast()), 1, 2, anchorLeft = 1)
+ grid.setField(Label("Gateway:"), 0, 3, anchorRight = 1)
+ grid.setField(Label(self.__config.get_ipv4_gateway()), 1, 3, anchorLeft = 1)
+ grid.setField(Label("Size:"), 0, 4, anchorRight = 1)
+ grid.setField(Label("%d addresses" % self.__config.get_ipv4_max_addresses()), 1, 4, anchorLeft = 1)
+ grid.setField(Label("Type:"), 0, 5, anchorRight = 1)
+ grid.setField(Label(self.__config.get_ipv4_network_type()), 1, 5, anchorLeft = 1)
+ return [Label("Network Details"),
+ grid]
+
+ def get_public_network_alert_page(self, screen):
+ grid = Grid(1, 2)
+ grid.setField(Label("The network should normally use a private IPv4 address."), 0, 0, anchorLeft = 1)
+ grid.setField(Label("Use this non-private address anyway?"), 0, 1, anchorLeft = 1)
+ return [Label("Check Network Address"),
+ grid]
+
+ def get_dhcp_range_page(self, screen):
+ self.__start_address = Entry(15, self.__config.get_ipv4_start_address())
+ self.__end_address = Entry(15, self.__config.get_ipv4_end_address())
+ grid = Grid(2,2)
+ grid.setField(Label("Start:"), 0, 0, anchorRight = 1)
+ grid.setField(self.__start_address, 1, 0, anchorLeft = 1)
+ grid.setField(Label("End:"), 0, 1, anchorRight = 1)
+ grid.setField(self.__end_address, 1, 1, anchorLeft = 1)
+ return [Label("Selecting The DHCP Range"),
+ grid,
+ Label("TIP: Unless you wish to reserve some addresses to allow static network"),
+ Label("configuration in virtual machines, these paraemters can be left with"),
+ Label("their default values.")]
+
+ def get_network_type_page(self, screen):
+ self.__isolated_network = Checkbox("Isolated virtual network",
+ self.__config.is_isolated_network())
+ grid = Grid(1, 3)
+ grid.setField(Label("Please indicate whether this virtual network should be"), 0, 0, anchorLeft = 1)
+ grid.setField(Label("connected to the physical network."), 0, 1, anchorLeft = 1)
+ grid.setField(self.__isolated_network, 0, 2)
+ return [Label("Connecting To Physical Network"),
+ grid]
+
+ def get_select_physical_network_page(self, screen):
+ devices = []
+ devices.append(["NAT to any physical device", "", self.__config.get_physical_device() == ""])
+ for device in self.get_hal().list_network_devices():
+ devices.append(["NAT to physical device %s" % device, device, self.__config.get_physical_device() == device])
+ self.__physical_devices = RadioBar(screen, (devices))
+ grid = Grid(1, 2)
+ grid.setField(Label("Forward to physical network:"), 0, 0)
+ grid.setField(self.__physical_devices, 0, 1)
+ return [Label("Connecting To Physical Network"),
+ grid]
+
+ def get_summary_page(self, screen):
+ grid1 = Grid(2, 1)
+ grid1.setField(Label("Network name:"), 0, 0, anchorRight = 1)
+ grid1.setField(Label(self.__config.get_name()), 1, 0, anchorLeft = 1)
+
+ grid2 = Grid(2, 3)
+ grid2.setField(Label("Network:"), 0, 0, anchorRight = 1)
+ grid2.setField(Label(self.__config.get_ipv4_address()), 1, 0, anchorLeft = 1)
+ grid2.setField(Label("Gateway:"), 0, 1, anchorRight = 1)
+ grid2.setField(Label(self.__config.get_ipv4_gateway()), 1, 1, anchorLeft = 1)
+ grid2.setField(Label("Netmask:"), 0, 2, anchorRight = 1)
+ grid2.setField(Label(self.__config.get_ipv4_netmask()), 1, 2, anchorLeft = 1)
+
+ grid3 = Grid(2, 2)
+ grid3.setField(Label("Start address:"), 0, 0, anchorRight = 1)
+ grid3.setField(Label(self.__config.get_ipv4_start_address()), 1, 0, anchorLeft = 1)
+ grid3.setField(Label("End address:"), 0, 1, anchorRight = 1)
+ grid3.setField(Label(self.__config.get_ipv4_end_address()), 1, 1, anchorLeft = 1)
+
+ grid4 = Grid(2, 1)
+ grid4.setField(Label("Connectivity:"), 0, 0, anchorRight = 1)
+ if self.__config.is_isolated_network():
+ grid4.setField(Label("Isolated virtual network"), 1, 0, anchorLeft = 1)
+ else:
+ grid4.setField(Label("NAT to %s" % self.__config.get_physical_device_text()), 1, 0, anchorLeft = 1)
+
+ return [Label("Ready To Create Network"),
+ Label("Summary"),
+ grid1,
+ Label("IPv4 Network"),
+ grid2,
+ Label("DHCP"),
+ grid3,
+ Label("Forwarding"),
+ grid4]
+
+def DefineNetwork():
+ screen = DefineNetworkConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/destroynetwork.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/destroynetwork.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# destroynetwork.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_PAGE = 1
+DESTROY_PAGE = 2
+
+class DestroyNetworkConfigScreen(NetworkListConfigScreen):
+ def __init__(self):
+ NetworkListConfigScreen.__init__(self, "Destroy A Network")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_PAGE: return self.get_network_list_page(screen, defined = False)
+ elif page is DESTROY_PAGE: return self.get_destroy_network_page(screen)
+
+ def page_has_next(self, page):
+ if page is LIST_PAGE: return self.has_selectable_networks()
+ return False
+
+ def page_has_back(self, page):
+ if page is DESTROY_PAGE: return True
+ return False
+
+ def validate_input(self, page, errors):
+ if page is LIST_PAGE:
+ network = self.get_selected_network()
+ self.get_libvirt().destroy_network(network)
+ return True
+ return False
+
+ def get_destroy_network_page(self, screen):
+ return [Label("Network Destroyed"),
+ Label("%s has been destroyed." % self.get_selected_network())]
+
+def DestroyNetwork():
+ screen = DestroyNetworkConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/domainconfig.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/domainconfig.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,224 @@
+# domainconfig.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from virtinst import Guest
+
+class DomainConfig:
+ LOCAL_INSTALL = "local"
+ NETWORK_INSTALL = "network"
+ PXE_INSTALL = "pxe"
+ INSTALL_TYPE_TEXT = {LOCAL_INSTALL : "Local CDROM/ISO",
+ NETWORK_INSTALL : "URL INstall Tree",
+ PXE_INSTALL : "PXE Install"}
+
+ INSTALL_SOURCE_CDROM = "cdrom"
+ INSTALL_SOURCE_ISO = "iso"
+
+ NEW_STORAGE = "new"
+ EXISTING_STORAGE = "existing"
+
+ def __init__(self):
+ self.__guest_name = ""
+ self.__install_type = DomainConfig.LOCAL_INSTALL
+ self.__use_cdrom_source = True
+ self.__install_location = ""
+ self.__install_media = ""
+ self.__iso_path = ""
+ self.__install_url = ""
+ self.__kickstart_url = ""
+ self.__kernel_options = ""
+ self.__os_type = "other"
+ self.__os_variant = None
+ self.__memory = 512
+ self.__cpus = 1
+ self.__enable_storage = True
+ self.__use_local_storage = True
+ self.__storage_size = 8.0
+ self.__allocate_storage = True
+ self.__storage_pool = ""
+ self.__storage_volume = ""
+ self.__network_bridge = None
+ self.__mac_address = None
+ self.__virt_type = None
+ self.__architecture = None
+
+ def set_guest_name(self, name):
+ self.__guest_name = name
+
+ def get_guest_name(self):
+ return self.__guest_name
+
+ def set_install_type(self, type):
+ self.__install_type = type
+
+ def get_install_type(self):
+ return self.__install_type
+
+ def get_install_type_text(self):
+ return DomainConfig.INSTALL_TYPE_TEXT[self.get_install_type()]
+
+ def is_install_type(self, type):
+ return self.__install_type == type
+
+ def set_install_location(self, location):
+ self.__install_location = location
+
+ def set_use_cdrom_source(self, use):
+ self.__use_cdrom_source = use
+
+ def get_use_cdrom_source(self):
+ return self.__use_cdrom_source
+
+ def get_install_location(self):
+ return self.__install_location
+
+ def is_install_location(self, location):
+ return self.__install_location == location
+
+ def set_install_media(self, media):
+ self.__install_media = media
+
+ def get_install_media(self):
+ return self.__install_media
+
+ def is_install_media(self, media):
+ return self.__install_media == media
+
+ def set_iso_path(self, path):
+ self.__iso_path = path
+
+ def get_iso_path(self):
+ return self.__iso_path
+
+ def set_install_url(self, url):
+ self.__install_url = url
+
+ def get_install_url(self):
+ return self.__install_url
+
+ def set_kickstart_url(self, url):
+ self.__kickstart_url = url
+
+ def get_kickstart_url(self):
+ return self.__kickstart_url
+
+ def set_kernel_options(self, options):
+ self.__kernel_options = options
+
+ def get_kernel_options(self):
+ return self.__kernel_options
+
+ def set_os_type(self, type):
+ self.__os_type = type
+ self.__os_variant = Guest.list_os_variants(type)[0]
+
+ def get_os_type(self):
+ return self.__os_type
+
+ def is_os_type(self, type):
+ return self.__os_type == type
+
+ def set_os_variant(self, variant):
+ self.__os_variant = variant
+
+ def get_os_variant(self):
+ return self.__os_variant
+
+ def is_os_variant(self, variant):
+ return self.__os_variant == variant
+
+ def set_memory(self, memory):
+ self.__memory = int(memory)
+
+ def get_memory(self):
+ return self.__memory
+
+ def set_cpus(self, cpus):
+ self.__cpus = cpus
+
+ def get_cpus(self):
+ return self.__cpus
+
+ def set_enable_storage(self, enable):
+ self.__enable_storage = enable
+
+ def get_enable_storage(self):
+ return self.__enable_storage
+
+ def set_use_local_storage(self, use):
+ self.__use_local_storage = use
+
+ def get_use_local_storage(self):
+ return self.__use_local_storage
+
+ def set_storage_size(self, size):
+ self.__storage_size = size
+
+ def get_storage_size(self):
+ return self.__storage_size
+
+ def set_allocate_storage(self, allocate):
+ self.__allocate_storage = allocate
+
+ def get_allocate_storage(self):
+ return self.__allocate_storage
+
+ def set_storage_pool(self, pool):
+ self.__storage_pool = pool
+
+ def get_storage_pool(self):
+ return self.__storage_pool
+
+ def set_storage_volume(self, volume):
+ self.__storage_volume = volume
+
+ def get_storage_volume(self):
+ return self.__storage_volume
+
+ def is_existing_storage(self, storage):
+ return self.__existing_storage == storage
+
+ def set_network_bridge(self, bridge):
+ self.__network_bridge = bridge
+
+ def get_network_bridge(self):
+ return self.__network_bridge
+
+ def set_mac_address(self, address):
+ self.__mac_address = address
+
+ def get_mac_address(self):
+ return self.__mac_address
+
+ def set_virt_type(self, type):
+ self.__virt_type = type
+
+ def get_virt_type(self):
+ return self.__virt_type
+
+ def is_virt_type(self, type):
+ return self.__virt_type == type
+
+ def set_architecture(self, architecture):
+ self.__architecture = architecture
+
+ def get_architecture(self):
+ return self.__architecture
+
+ def is_architecture(self, architecture):
+ return self.__architecture == architecture
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/halworker.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/halworker.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,45 @@
+# halworker.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import dbus
+import virtinst
+
+class HALWorker:
+ '''Provides utilities for working with HAL to get hardware information.'''
+ def __init__(self):
+ self.__bus = dbus.SystemBus()
+ hobj = self.__bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
+ self.__conn = dbus.Interface(hobj, "org.freedesktop.Hal.Manager")
+
+ def list_installable_volumes(self):
+ result = {}
+ for udi in self.__conn.FindDeviceByCapability("volume"):
+ device = self.__bus.get_object("org.freedesktop.Hal", udi)
+ info = dbus.Interface(device, "org.freedesktop.Hal.Device")
+ if info.GetProperty("volume.is_disc"):
+ if info.GetProperty("volume.disc.has_data"):
+ result[str(info.GetProperty("block.device"))] = info.GetProperty("volume.label")
+ return result
+
+ def list_network_devices(self):
+ result = []
+ for udi in self.__conn.FindDeviceByCapability("net"):
+ device = self.__bus.get_object("org.freedesktop.Hal", udi)
+ info = dbus.Interface(device, "org.freedesktop.Hal.Device")
+ result.append(info.GetProperty("net.interface"))
+ return result
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/hostconnect.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/hostconnect.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,29 @@
+# hostconnect.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+from configscreen import *
+
+class HostConnectConfigScreen(ConfigScreen):
+ def __init__(self):
+ ConfigScree
+
+def HostConnect():
+ screen = HostConnectConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/hostmenu.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/hostmenu.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,46 @@
+# hostmenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+from menuscreen import MenuScreen
+from changehost import ChangeHost
+from addhost import AddHost
+from removehost import RemoveHost
+
+SELECT_HOST = 1
+ADD_HOST = 2
+REMOVE_HOST = 3
+
+class HostMenuScreen(MenuScreen):
+ def __init__(self):
+ MenuScreen.__init__(self, "Host Menu Screen")
+
+ def get_menu_items(self):
+ return (("Select A Host", SELECT_HOST),
+ ("Add A Host", ADD_HOST),
+ ("Remove A Host", REMOVE_HOST))
+
+ def handle_selection(self, item):
+ if item is SELECT_HOST: ChangeHost()
+ elif item is ADD_HOST: AddHost()
+ elif item is REMOVE_HOST: RemoveHost()
+
+def HostMenu():
+ screen = HostMenuScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/libvirtworker.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/libvirtworker.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,461 @@
+# libvirtworker.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import dbus
+import libvirt
+import os
+import virtinst
+import utils
+import logging
+
+from domainconfig import DomainConfig
+
+DEFAULT_POOL_TARGET_PATH="/var/lib/libvirt/images"
+DEFAULT_URL="qemu:///system"
+
+default_url = DEFAULT_URL
+
+def set_default_url(url):
+ logging.info("Changing DEFAULT_URL to %s" % url)
+ global default_url
+
+ default_url = url
+
+def get_default_url():
+ logging.info("Returning default URL of %s" % default_url)
+ return default_url
+
+class VirtManagerConfig:
+ def __init__(self, filename = "/etc/remote-libvirt.conf"):
+ self.__filename = filename
+
+ def get_connection_list(self):
+ result = []
+ if os.path.exists(self.__filename):
+ input = file(self.__filename, "r")
+ for entry in input: result.append(entry[0:-1])
+ return result
+
+ def add_connection(self, connection):
+ connections = self.get_connection_list()
+ if connections.count(connection) is 0:
+ connections.append(connection)
+ self._save_connections(connections)
+
+ def remove_connection(self, connection):
+ connections = self.get_connection_list()
+ if connections.count(connection) > 0:
+ connections.remove(connection)
+ self._save_connections(connections)
+
+ def _save_connections(self, connections):
+ output = file(self.__filename, "w")
+ for entry in connections:
+ print >> output, entry
+ output.close
+
+class LibvirtWorker:
+ '''Provides utilities for interfacing with libvirt.'''
+ def __init__(self, url = None):
+ if url is None: url = get_default_url()
+ logging.info("Connecting to libvirt: %s" % url)
+ self.__url = None
+ self.__conn = None
+ self.open_connection(url)
+ self.__capabilities = virtinst.CapabilitiesParser.parse(self.__conn.getCapabilities())
+ self.__net = virtinst.VirtualNetworkInterface(conn = self.__conn)
+ self.__net.setup(self.__conn)
+ (self.__new_guest, self.__new_domain) = virtinst.CapabilitiesParser.guest_lookup(conn = self.__conn)
+
+ def get_connection(self):
+ '''Returns the underlying connection.'''
+ return self.__conn
+
+ def get_url(self):
+ return self.__url
+
+ def open_connection(self, url):
+ '''Lets the user change the url for the connection.'''
+ old_conn = self.__conn
+ old_url = self.__url
+ try:
+ self.__conn = libvirt.open(url)
+ self.__url = url
+ set_default_url(url)
+ except Exception, error:
+ self.__conn = old_conn
+ self.__url = old_url
+ raise error
+
+ def list_domains(self, defined = True, started = True):
+ '''Lists all domains.'''
+ result = []
+ if defined:
+ result.extend(self.__conn.listDefinedDomains())
+ if started:
+ for id in self.__conn.listDomainsID():
+ result.append(self.__conn.lookupByID(id).name())
+ return result
+
+ def get_domain(self, name):
+ '''Returns the specified domain.'''
+ result = self.__conn.lookupByName(name)
+ if result is None: raise Exception("No such domain exists: %s" % name)
+
+ return result
+
+ def domain_exists(self, name):
+ '''Returns whether a domain with the specified node exists.'''
+ domains = self.list_domains()
+ if name in domains: return True
+ return False
+
+ def create_domain(self, name):
+ '''Creates the specified domain.'''
+ domain = self.get_domain(name)
+ domain.create()
+
+ def destroy_domain(self, name):
+ '''Destroys the specified domain.'''
+ domain = self.get_domain(name)
+ domain.destroy()
+
+ def undefine_domain(self, name):
+ '''Undefines the specified domain.'''
+ domain = self.get_domain(name)
+ domain.undefine()
+
+ def migrate_domain(self, name, target):
+ '''Migrates the specified domain to the target machine.'''
+ target_conn = libvirt.open(target)
+ virtmachine = self.get_domain(name)
+ virtmachine.migrate(target_conn, libvirt.VIR_MIGRATE_LIVE, None, None, 0)
+
+ def list_networks(self, defined = True, started = True):
+ '''Lists all networks.'''
+ result = []
+ if defined: result.extend(self.__conn.listDefinedNetworks())
+ if started: result.extend(self.__conn.listNetworks())
+ return result
+
+ def get_network(self, name):
+ '''Returns the specified network.'''
+ result = self.__conn.networkLookupByName(name)
+ if result is None: raise Exception("No such network exists: %s" % name)
+
+ return result
+
+ def network_exists(self, name):
+ '''Returns if a network with the given name already exists.'''
+ networks = self.list_networks()
+ if name in networks: return True
+ return False
+
+ def define_network(self, config):
+ '''Defines a new network.'''
+ # since there's no other way currently, we'll have to use XML
+ name = config.get_name()
+ ip = config.get_ipv4_address_raw()
+ start = config.get_ipv4_start_address()
+ end = config.get_ipv4_end_address()
+ fw = config.get_physical_device()
+
+ xml = "<network>" + \
+ " <name>%s</name>\n" % name
+ if not config.is_public_ipv4_network():
+ if fw is not "":
+ xml += " <forward dev='%s'/>\n" % fw[1]
+ else:
+ xml += " <forward/>\n"
+
+ xml += " <ip address='%s' netmask='%s'>\n" % (str(ip[1]), str(ip.netmask()))
+ xml += " <dhcp>\n"
+ xml += " <range start='%s' end='%s'/>\n" % (str(start), str(end))
+ xml += " </dhcp>\n"
+ xml += " </ip>\n"
+ xml += "</network>\n"
+
+ self.__conn.networkDefineXML(xml)
+
+ def create_network(self, name):
+ '''Creates a defined network.'''
+ network = self.get_network(name)
+ network.create()
+
+ def destroy_network(self, name):
+ '''Destroys the specified network.'''
+ network = self.get_network(name)
+ network.destroy()
+
+ def undefine_network(self, name):
+ '''Undefines the specified network.'''
+ network = self.get_network(name)
+ network.undefine()
+
+ def list_storage_pools(self, defined=True, created=True):
+ '''Returns the list of all defined storage pools.'''
+ pools = []
+ if defined: pools.extend(self.__conn.listDefinedStoragePools())
+ if created: pools.extend(self.__conn.listStoragePools())
+ return pools
+
+ def storage_pool_exists(self, name):
+ '''Returns whether a storage pool exists.'''
+ pools = self.list_storage_pools()
+ if name in pools: return True
+ return False
+
+ def create_storage_pool(self, name):
+ '''Starts the named storage pool if it is not currently started.'''
+ if name not in self.list_storage_pools(defined = False):
+ pool = self.get_storage_pool(name)
+ pool.create(0)
+
+ def destroy_storage_pool(self, name):
+ '''Stops the specified storage pool.'''
+ if name in self.list_storage_pools(defined = False):
+ pool = self.get_storage_pool(name)
+ pool.destroy()
+
+ def define_storage_pool(self, name, config = None, meter = None):
+ '''Defines a storage pool with the given name.'''
+ if config is None:
+ pool = virtinst.Storage.DirectoryPool(conn=self.__conn,
+ name=name,
+ target_path=DEFAULT_POOL_TARGET_PATH)
+ newpool = pool.install(build=True, create=True, meter=meter)
+ newpool.setAutostart(True)
+ else:
+ pool = config.get_pool()
+ pool.target_path = config.get_target_path()
+ if config.needs_hostname():
+ pool.host = config.get_hostname()
+ if config.needs_source_path():
+ pool.source_path = config.get_source_path()
+ if config.needs_format():
+ pool.format = config.get_format()
+ pool.conn = self.__conn
+ pool.get_xml_config()
+ newpool = pool.install(meter=meter,
+ build=True, # config.get_build_pool(),
+ create=True)
+ newpool.setAutostart(True)
+
+ def undefine_storage_pool(self, name):
+ '''Undefines the specified storage pool.'''
+ pool = self.get_storage_pool(name)
+ pool.undefine()
+
+ def get_storage_pool(self, name):
+ '''Returns the storage pool with the specified name.'''
+ return self.__conn.storagePoolLookupByName(name)
+
+ def list_storage_volumes(self, poolname):
+ '''Returns the list of all defined storage volumes for a given pool.'''
+ pool = self.get_storage_pool(poolname)
+ return pool.listVolumes()
+
+ def define_storage_volume(self, config, meter):
+ '''Defines a new storage volume.'''
+ self.create_storage_pool(config.get_pool().name())
+ volume = config.create_volume()
+ volume.install(meter = meter)
+
+ def remove_storage_volume(self, poolname, volumename):
+ '''Removes the specified storage volume.'''
+ volume = self.get_storage_volume(poolname, volumename)
+ volume.delete(0)
+
+ def get_storage_volume(self, poolname, volumename):
+ '''Returns a reference to the specified storage volume.'''
+ pool =self.get_storage_pool(poolname)
+ volume = pool.storageVolLookupByName(volumename)
+ return volume
+
+ def list_bridges(self):
+ '''Lists all defined and active bridges.'''
+ bridges = self.__conn.listNetworks()
+ bridges.extend(self.__conn.listDefinedNetworks())
+ result = []
+ for name in bridges:
+ bridge = self.__conn.networkLookupByName(name)
+ result.append(bridge)
+ return result
+
+ def generate_mac_address(self):
+ return self.__net.macaddr
+
+ def get_storage_size(self, poolname, volumename):
+ '''Returns the size of the specified storage volume.'''
+ volume = self.get_storage_volume(poolname, volumename)
+ return volume.info()[1] / (1024.0 ** 3)
+
+ def get_virt_types(self):
+ result = []
+ for guest in self.__capabilities.guests:
+ guest_type = guest.os_type
+ for domain in guest.domains:
+ domain_type = domain.hypervisor_type
+ label = domain_type
+
+ if domain_type is "kvm" and guest_type is "xen": label = "xenner"
+ elif domain_type is "xen":
+ if guest_type is "xen":
+ label = "xen (paravirt)"
+ elif guest_type is "kvm":
+ label = "xen (fullvirt)"
+ elif domain_type is "test":
+ if guest_type is "xen":
+ label = "test (xen)"
+ elif guest_type is "hvm":
+ label = "test (hvm)"
+
+ for row in result:
+ if row[0] == label:
+ label = None
+ break
+ if label is None: continue
+
+ result.append([label, domain_type, guest_type])
+ return result
+
+ def list_virt_types(self):
+ virt_types = self.get_virt_types()
+ result = []
+ for type in virt_types:
+ result.append(type[0])
+ return result
+
+ def get_default_architecture(self):
+ '''Returns a default hypervisor type for new domains.'''
+ return self.__new_guest.arch
+
+ def get_hypervisor(self, virt_type):
+ virt_types = self.get_virt_types()
+ for type in virt_types:
+ if type[0] is virt_type: return type[1]
+ return None
+
+ def get_default_virt_type(self):
+ '''Returns the default virtualization type for new domains.'''
+ return self.__new_domain.hypervisor_type
+
+ def get_os_type(self, virt_type):
+ virt_types = self.get_virt_types()
+ for type in virt_types:
+ if type[0] is virt_type: return type[2]
+ return None
+
+ def list_architectures(self):
+ result = []
+ for guest in self.__capabilities.guests:
+ for domain in guest.domains:
+ label = guest.arch
+ for row in result:
+ if row == label:
+ label = None
+ break
+ if label is None: continue
+
+ result.append(label)
+ return result
+
+ def define_domain(self, config, meter):
+ location = extra = kickstart = None
+
+ if config.get_install_type() == DomainConfig.LOCAL_INSTALL:
+ if config.get_use_cdrom_source():
+ iclass = virtinst.DistroInstaller
+ location = config.get_install_media()
+ else:
+ iclass = virtinst.LiveCDInstaller
+ location = config.get_iso_path()
+ elif config.get_install_type() == DomainConfig.NETWORK_INSTALL:
+ iclass = virtinst.DistroInstaller
+ location = config.get_install_url()
+ extra = config.get_kernel_options()
+ kickstart = config.get_kickstart_url()
+ elif config.get_install_type() == DomainConfig.PXE_INSTALL:
+ iclass = virtinst.PXEInstaller
+
+ installer = iclass(conn = self.__conn,
+ type = self.get_hypervisor(config.get_virt_type()),
+ os_type = self.get_os_type(config.get_virt_type()))
+ self.__guest = installer.guest_from_installer()
+ self.__guest.name = config.get_guest_name()
+ self.__guest.vcpus = config.get_cpus()
+ self.__guest.memory = config.get_memory()
+ self.__guest.maxmemory = config.get_memory()
+
+ self.__guest.installer.location = location
+ if config.get_use_cdrom_source(): self.__guest.installer.cdrom = True
+ extraargs = ""
+ if extra: extraargs += extra
+ if kickstart: extraargs += " ks=%s" % kickstart
+ if extraargs: self.__guest.installer.extraarags = extraargs
+
+ self.__guest.uuid = virtinst.util.uuidToString(virtinst.util.randomUUID())
+
+ if config.get_os_type() != "generic": self.__guest.os_type = config.get_os_type()
+ if config.get_os_variant() != "generic": self.__guest.os_variant = config.get_os_variant()
+
+ self.__guest._graphics_dev = virtinst.VirtualGraphics(type = virtinst.VirtualGraphics.TYPE_VNC)
+ self.__guest.sound_devs = []
+ self.__guest.sound_devs.append(virtinst.VirtualAudio(model = "es1370"))
+
+ self._setup_nics(config)
+ self._setup_disks(config)
+
+ self.__guest.conn = self.__conn
+ self.__domain = self.__guest.start_install(False, meter = meter)
+
+ def _setup_nics(self, config):
+ self.__guest.nics = []
+ nic = virtinst.VirtualNetworkInterface(type = virtinst.VirtualNetworkInterface.TYPE_VIRTUAL,
+ bridge = config.get_network_bridge(),
+ network = config.get_network_bridge(),
+ macaddr = config.get_mac_address())
+ self.__guest.nics.append(nic)
+ # ensure the network is running
+ if config.get_network_bridge() not in self.__conn.listNetworks():
+ network = self.__conn.networkLookupByName(config.get_network_bridge())
+ network.create()
+
+ def _setup_disks(self, config):
+ self.__guest.disks = []
+ if config.get_enable_storage():
+ path = None
+ if config.get_use_local_storage():
+ if self.storage_pool_exists("default") is False:
+ self.define_storage_pool("default")
+ pool = self.__conn.storagePoolLookupByName("default")
+ path = virtinst.Storage.StorageVolume.find_free_name(config.get_guest_name(),
+ pool_object = pool,
+ suffix = ".img")
+ path = os.path.join(DEFAULT_POOL_TARGET_PATH, path)
+ else:
+ volume = self.get_storage_volume(config.get_storage_pool(),
+ config.get_storage_volume())
+ path = volume.path()
+
+ if path is not None:
+ storage= virtinst.VirtualDisk(conn = self.__conn,
+ path = path,
+ size = config.get_storage_size())
+ self.__guest.disks.append(storage)
+ self.__guest.conn = self.__conn
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/listdomains.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/listdomains.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# listdomains.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from libvirtworker import LibvirtWorker
+from configscreen import *
+
+class ListDomainsConfigScreen(DomainListConfigScreen):
+ LIST_PAGE = 1
+ DETAIL_PAGE = 2
+
+ def __init__(self):
+ DomainListConfigScreen.__init__(self, 'List Virtual Machines')
+
+ def page_has_next(self, page):
+ return (page == self.LIST_PAGE)
+
+ def page_has_back(self, page):
+ return (page == self.DETAIL_PAGE)
+
+ def validate_input(self, page, errors):
+ if page == self.LIST_PAGE:
+ if self.get_selected_domain() is None:
+ errors.append("Please select a virtual machine to view.")
+ else:
+ return True
+
+ def get_elements_for_page(self, screen, page):
+ if page == self.LIST_PAGE:
+ return self.get_domain_list_page(screen)
+ elif page == self.DETAIL_PAGE:
+ return self.get_detail_page_elements(screen)
+
+ def get_detail_page_elements(self, screen):
+ domain = self.get_libvirt().get_domain(self.get_selected_domain())
+ grid = Grid(2, 5)
+ grid.setField(Label("Name: "), 0, 0, anchorRight = 1)
+ grid.setField(Label(domain.name()), 1, 0, anchorLeft = 1)
+ grid.setField(Label("UUID: "), 0, 1, anchorRight = 1)
+ grid.setField(Label(domain.UUIDString()), 1, 1, anchorLeft = 1)
+ grid.setField(Label("OS Type: "), 0, 2, anchorRight = 1)
+ grid.setField(Label(domain.OSType()), 1, 2, anchorLeft = 1)
+ grid.setField(Label("Max. Memory: "), 0, 3, anchorRight = 1)
+ grid.setField(Label(str(domain.maxMemory())), 1, 3, anchorLeft = 1)
+ grid.setField(Label("Max. VCPUs: "), 0, 4, anchorRight = 1)
+ grid.setField(Label(str(domain.maxVcpus())), 1, 4, anchorLeft = 1)
+ return [grid]
+
+def ListDomains():
+ screen = ListDomainsConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/listnetworks.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/listnetworks.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,55 @@
+# listnetworks.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from configscreen import *
+
+LIST_PAGE = 1
+DETAILS_PAGE = 2
+
+class ListNetworksConfigScreen(NetworkListConfigScreen):
+ def __init__(self):
+ NetworkListConfigScreen.__init__(self, "List Networks")
+
+ def page_has_next(self, page):
+ return (page is LIST_PAGE) and self.has_selectable_networks()
+
+ def page_has_back(self, page):
+ return (page is DETAILS_PAGE)
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_PAGE: return self.get_network_list_page(screen)
+ elif page is DETAILS_PAGE: return self.get_network_details_page(screen)
+
+ def get_network_details_page(self, screen):
+ network = self.get_libvirt().get_network(self.get_selected_network())
+ grid = Grid(2, 3)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(network.name()), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Autostart:"), 0, 1, anchorRight = 1)
+ label = "No"
+ if network.autostart(): label = "Yes"
+ grid.setField(Label(label), 1, 1, anchorLeft = 1)
+ if network.bridgeName() is not "":
+ grid.setField(Label("Bridge:"), 0, 2, anchorRight = 1)
+ grid.setField(Label(network.bridgeName()), 1, 2, anchorLeft = 1)
+ return [Label("Network Interface Details"),
+ grid]
+
+def ListNetworks():
+ screen = ListNetworksConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/listpools.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/listpools.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,64 @@
+# listpools.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+from configscreen import *
+from utils import *
+
+LIST_PAGE = 1
+DETAILS_PAGE = 2
+
+class ListStoragePoolsConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "List Storage Pools")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_PAGE: return self.get_storage_pool_list_page(screen)
+ elif page is DETAILS_PAGE: return self.get_pool_details_page(screen)
+
+ def page_has_next(self, page):
+ if page is LIST_PAGE and self.has_selectable_pools():
+ return True
+ return False
+
+ def page_has_back(self, page):
+ if page is DETAILS_PAGE: return True
+ return False
+
+ def get_pool_details_page(self, screen):
+ pool = self.get_libvirt().get_storage_pool(self.get_selected_pool())
+ volumes = Listbox(0);
+ for name in pool.listVolumes():
+ volume = pool.storageVolLookupByName(name)
+ volumes.append("%s (%s)" % (name, size_as_mb_or_gb(volume.info()[1])), name)
+ grid = Grid(2, 3)
+ grid.setField(Label("Name:"), 0, 0, anchorRight = 1)
+ grid.setField(Label(pool.name()), 1, 0, anchorLeft = 1)
+ grid.setField(Label("Volumes:"), 0, 1, anchorRight = 1)
+ grid.setField(volumes, 1, 1, anchorLeft = 1)
+ grid.setField(Label("Autostart:"), 0, 2, anchorRight = 1)
+ label = "No"
+ if pool.autostart(): label = "Yes"
+ grid.setField(Label(label), 1, 2, anchorLeft = 1)
+ return [Label("Details For Storage Pool: %s" % self.get_selected_pool()),
+ grid]
+
+def ListStoragePools():
+ screen = ListStoragePoolsConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/mainmenu.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/mainmenu.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,55 @@
+# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from menuscreen import MenuScreen
+from nodemenu import NodeMenu
+from netmenu import NetworkMenu
+from storagemenu import StoragePoolMenu
+from hostmenu import HostMenu
+
+import utils
+import logging
+
+NODE_MENU = 1
+NETWORK_MENU = 2
+STORAGE_MENU = 3
+HOST_MENU = 4
+EXIT_CONSOLE = 99
+
+class MainMenuScreen(MenuScreen):
+ def __init__(self):
+ MenuScreen.__init__(self, "Main Menu")
+
+ def get_menu_items(self):
+ return (("Node Administration", NODE_MENU),
+ ("Network Administration", NETWORK_MENU),
+ ("Storage Pool Administration", STORAGE_MENU),
+ ("Host Administration", HOST_MENU))
+
+ def handle_selection(self, page):
+ if page is NODE_MENU: NodeMenu()
+ elif page is NETWORK_MENU: NetworkMenu()
+ elif page is STORAGE_MENU: StoragePoolMenu()
+ elif page is HOST_MENU: HostMenu()
+
+def MainMenu():
+ screen = MainMenuScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/menuscreen.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/menuscreen.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,57 @@
+# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+import utils
+import logging
+
+EXIT_MENU = 99
+
+class MenuScreen:
+ def __init__(self, title):
+ self.__title = title
+
+ def start(self):
+ finished = False
+ while finished == False:
+ screen = SnackScreen()
+ menu = Listbox(height = 0, width = 0, returnExit = 1)
+ for menu_item in self.get_menu_items():
+ menu.append(menu_item[0], menu_item[1])
+ menu.append("Exit Menu", EXIT_MENU)
+ gridform = GridForm(screen, self.__title, 1, 4)
+ gridform.add(menu, 0, 0)
+ result = gridform.run();
+ screen.popWindow()
+ screen.finish()
+
+ try:
+ if result.current() == EXIT_MENU: finished = True
+ else: self.handle_selection(result.current())
+ except Exception, error:
+ screen = SnackScreen()
+ logging.info("An exception occurred: %s" % str(error))
+ ButtonChoiceWindow(screen,
+ "An Exception Has Occurred",
+ str(error) + "\n" + traceback.format_exc(),
+ buttons = ["OK"])
+ screen.popWindow()
+ screen.finish()
+ finished = True
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/migratedomain.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/migratedomain.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# migratedomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from libvirtworker import LibvirtWorker
+from configscreen import *
+
+LIST_DOMAINS = 1
+SELECT_TARGET = 2
+CONFIRM_PAGE = 3
+
+class MigrateDomainConfigScreen(DomainListConfigScreen):
+ def __init__(self):
+ DomainListConfigScreen.__init__(self, "Migrate Virtual Machine")
+ self.__configured = False
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_DOMAINS: return self.get_domain_list_page(screen)
+ elif page is SELECT_TARGET: return self.get_target_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ if page is LIST_DOMAINS: return self.has_selectable_domains()
+ else: return page < CONFIRM_PAGE
+
+ def page_has_back(self, page):
+ return page < CONFIRM_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def validate_input(self, page, errors):
+ if page is LIST_DOMAINS: return self.get_selected_domain() is not None
+ elif page is SELECT_TARGET:
+ if self.__targets.current() is None:
+ errors.append("Please enter a target hostname or IP address.")
+ return False
+ elif page is CONFIRM_PAGE:
+ if not self.__confirm.value():
+ errors.append("You must confirm migrating this virtual machine to proceed.")
+ return False
+ return True
+
+ def process_input(self, page):
+ if page is CONFIRM_PAGE:
+ self.get_libvirt().migrate_domain(self.get_selected_domain(), self.__targets.current())
+ self.set_finished()
+
+ def get_target_page(self, screen):
+ self.__targets = Listbox(0)
+ for connection in self.get_virt_manager_config().get_connection_list():
+ self.__targets.append(connection, connection)
+ return [Label("Select A Target Host"),
+ self.__targets]
+
+ def get_confirm_page(self, screen):
+ self.__confirm = Checkbox("Confirm migrating this virtual machine.")
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm, 0, 0)
+ return [grid]
+
+def MigrateDomain():
+ screen = MigrateDomainConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/netmenu.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/netmenu.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,58 @@
+# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from menuscreen import MenuScreen
+from definenet import DefineNetwork
+from createnetwork import CreateNetwork
+from destroynetwork import DestroyNetwork
+from undefinenetwork import UndefineNetwork
+from listnetworks import ListNetworks
+
+import utils
+import logging
+
+DEFINE_NETWORK = 1
+CREATE_NETWORK = 2
+DESTROY_NETWORK = 3
+UNDEFINE_NETWORK = 4
+LIST_NETWORKS = 5
+
+class NetworkMenuScreen(MenuScreen):
+ def __init__(self):
+ MenuScreen.__init__(self, "Network Administration")
+
+ def get_menu_items(self):
+ return (("Define A Network", DEFINE_NETWORK),
+ ("Create A Network", CREATE_NETWORK),
+ ("Destroy A Network", DESTROY_NETWORK),
+ ("Undefine A Network", UNDEFINE_NETWORK),
+ ("List Networks", LIST_NETWORKS))
+
+ def handle_selection(self, item):
+ if item is DEFINE_NETWORK: DefineNetwork()
+ elif item is CREATE_NETWORK: CreateNetwork()
+ elif item is DESTROY_NETWORK: DestroyNetwork()
+ elif item is UNDEFINE_NETWORK: UndefineNetwork()
+ elif item is LIST_NETWORKS: ListNetworks()
+
+def NetworkMenu():
+ screen = NetworkMenuScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/networkconfig.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/networkconfig.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,99 @@
+# networkconfig.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from IPy import IP
+import logging
+
+class NetworkConfig:
+ def __init__(self):
+ self.__name = ""
+ self.set_ipv4_address("192.168.100.0/24")
+ self.__isolated_network = True
+ self.__physical_device = ""
+
+ def set_name(self, name):
+ self.__name = name
+
+ def get_name(self):
+ return self.__name
+
+ def set_ipv4_address(self, address):
+ self.__ipv4_address = IP(address)
+ start = int(self.__ipv4_address.len() / 2)
+ end = self.__ipv4_address.len() - 2
+ self.__ipv4_start = str(self.__ipv4_address[start])
+ self.__ipv4_end = str(self.__ipv4_address[end])
+
+ def get_ipv4_address(self):
+ return self.__ipv4_address.strNormal()
+
+ def get_ipv4_address_raw(self):
+ return self.__ipv4_address
+
+ def get_ipv4_netmask(self):
+ return self.__ipv4_address.netmask().strNormal()
+
+ def get_ipv4_broadcast(self):
+ return self.__ipv4_address.broadcast().strNormal()
+
+ def get_ipv4_gateway(self):
+ return str(self.__ipv4_address[1])
+
+ def get_ipv4_max_addresses(self):
+ return self.__ipv4_address.len()
+
+ def get_ipv4_network_type(self):
+ return self.__ipv4_address.iptype()
+
+ def is_public_ipv4_network(self):
+ if self.__ipv4_address.iptype() is "PUBLIC":
+ return True
+ return False
+
+ def set_ipv4_start_address(self, address):
+ self.__ipv4_start = address
+
+ def get_ipv4_start_address(self):
+ return self.__ipv4_start
+
+ def set_ipv4_end_address(self, address):
+ self.__ipv4_end = address
+
+ def get_ipv4_end_address(self):
+ return self.__ipv4_end
+
+ def is_bad_address(self, address):
+ return not self.__ipv4_address.overlaps(address)
+
+ def set_isolated_network(self, isolated):
+ self.__isolated_network = isolated
+
+ def is_isolated_network(self):
+ return self.__isolated_network
+
+ def set_physical_device(self, device):
+ self.__physical_device = device
+
+ def get_physical_device(self):
+ return self.__physical_device
+
+ def get_physical_device_text(self):
+ if self.__physical_device == "":
+ return "any physical device"
+ else:
+ return "physical device %s" % self.__physical_device
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/nodeadmin.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/nodeadmin.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+#
+# node-admin - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import sys
+
+from mainmenu import MainMenu
+
+def NodeAdmin():
+ MainMenu()
+
+if __name__ == "__main__":
+ sys.exit(NodeAdmin())
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/nodemenu.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/nodemenu.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,67 @@
+# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from menuscreen import MenuScreen
+from configscreen import ConfigScreen
+from adddomain import AddDomain
+from startdomain import StartDomain
+from stopdomain import StopDomain
+from removedomain import RemoveDomain
+from listdomains import ListDomains
+from migratedomain import MigrateDomain
+from createuser import CreateUser
+
+import utils
+import logging
+
+ADD_DOMAIN = 1
+START_DOMAIN = 2
+STOP_DOMAIN = 3
+REMOVE_DOMAIN = 4
+LIST_DOMAINS = 5
+MIGRATE_DOMAIN = 6
+CREATE_USER = 7
+
+class NodeMenuScreen(MenuScreen):
+ def __init__(self):
+ MenuScreen.__init__(self, "Node Administration")
+
+ def get_menu_items(self):
+ return (("Add A Virtual Machine", ADD_DOMAIN),
+ ("Start A Virtual Machine", START_DOMAIN),
+ ("Stop A Virtual Machine", STOP_DOMAIN),
+ ("Remove A Virtual Machine", REMOVE_DOMAIN),
+ ("List All Virtual Machines", LIST_DOMAINS),
+ ("Migrate Virtual Machine", MIGRATE_DOMAIN),
+ ("Create A User", CREATE_USER))
+
+ def handle_selection(self, item):
+ if item is ADD_DOMAIN: AddDomain()
+ elif item is START_DOMAIN: StartDomain()
+ elif item is STOP_DOMAIN: StopDomain()
+ elif item is REMOVE_DOMAIN: RemoveDomain()
+ elif item is LIST_DOMAINS: ListDomains()
+ elif item is MIGRATE_DOMAIN: MigrateDomain()
+ elif item is CREATE_USER: CreateUser()
+
+def NodeMenu():
+ screen = NodeMenuScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/poolconfig.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/poolconfig.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,145 @@
+# poolconfig.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from virtinst import Storage
+
+ROOT_TARGET_PATH="/var/lib/libvirt/images/%s"
+
+class PoolConfig:
+ def __init__(self, libvirt):
+ self.__libvirt = libvirt
+ self.__name = ""
+ self.set_type(None)
+ self.__format = None
+ self.__hostname = ""
+ self.__target_path = ""
+ self.__source_path = ""
+ self.__build_pool = False
+
+ def get_pool(self):
+ return self.__pool
+
+ def set_name(self, name):
+ self.__name = name
+
+ def get_name(self):
+ return self.__name
+
+ def set_type(self, pooltype):
+ self.__type = pooltype
+ self.__needs_target_path = False
+ self.__needs_format = False
+ self.__needs_target_path = False
+ self.__needs_format = False
+ self.__needs_hostname = False
+ self.__needs_source_path = False
+ self.__needs_build_pool = False
+ if pooltype is not None:
+ if pooltype is Storage.StoragePool.TYPE_DIR:
+ self.__needs_target_path = True
+ self.__target_path = ROOT_TARGET_PATH % self.__name
+ self.__build_pool = True
+ elif pooltype is Storage.StoragePool.TYPE_DISK:
+ self.__needs_target_path = True
+ self.__needs_format = True
+ self.__needs_source_path = True
+ self.__needs_build_pool = True
+ elif pooltype is Storage.StoragePool.TYPE_FS:
+ self.__needs_target_path = True
+ self.__needs_format = True
+ self.__needs_source_path = True
+ self.__build_pool = True
+ elif pooltype is Storage.StoragePool.TYPE_ISCSI:
+ self.__needs_target_path = True
+ self.__needs_hostname = True
+ self.__needs_source_path = True
+ self.__build_pool = False
+ elif pooltype is Storage.StoragePool.TYPE_LOGICAL:
+ self.__needs_target_path = True
+ self.__needs_source_path = True
+ self.__needs_build_pool = True
+ elif pooltype is Storage.StoragePool.TYPE_NETFS:
+ self.__needs_target_path = True
+ self.__needs_format = True
+ self.__needs_hostname = True
+ self.__needs_source_path = True
+ self.__build_pool = True
+ # create pool
+ pool_class = Storage.StoragePool.get_pool_class(self.__type)
+ self.__pool = pool_class(name = self.__name,
+ conn = self.__libvirt.get_connection())
+ if self.__needs_format:
+ self.__format = self.__pool.formats[0]
+ else:
+ self.__type = Storage.StoragePool.get_pool_types()[0]
+
+ def get_type(self):
+ return self.__type
+
+ def needs_target_path(self):
+ return self.__needs_target_path
+
+ def needs_format(self):
+ return self.__needs_format
+
+ def needs_hostname(self):
+ return self.__needs_hostname
+
+ def source_must_be_absolute(self):
+ if self.__type is Storage.StoragePool.TYPE_ISCSI:
+ return False
+ return True
+
+ def needs_source_path(self):
+ return self.__needs_source_path
+
+ def needs_build_pool(self):
+ return self.__needs_build_pool
+
+ def set_target_path(self, path):
+ self.__target_path = path
+
+ def get_target_path(self):
+ return self.__target_path
+
+ def get_formats(self):
+ return self.__pool.formats
+
+ def set_format(self, format):
+ self.__format = format
+
+ def get_format(self):
+ return self.__format
+
+ def set_hostname(self, hostname):
+ self.__hostname = hostname
+
+ def get_hostname(self):
+ return self.__hostname
+
+ def set_source_path(self, source_path):
+ self.__source_path = source_path
+
+ def get_source_path(self):
+ return self.__source_path
+
+ def set_build_pool(self, build_pool):
+ self.__build_pool = build_pool
+
+ def get_build_pool(self):
+ return self.__build_pool
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/removedomain.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/removedomain.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# removedomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+class RemoveDomainConfigScreen(DomainListConfigScreen):
+ LIST_PAGE = 1
+ CONFIRM_PAGE = 2
+ REMOVE_PAGE = 3
+
+ def __init__(self):
+ DomainListConfigScreen.__init__(self, "Remove A Domain")
+
+ def get_elements_for_page(self, screen, page):
+ if page is self.LIST_PAGE: return self.get_domain_list_page(screen)
+ elif page is self.CONFIRM_PAGE: return self.get_confirm_page(screen)
+ elif page is self.REMOVE_PAGE: return self.get_remove_page(screen)
+
+ def page_has_next(self, page):
+ if page is self.LIST_PAGE: return self.has_selectable_domains()
+ elif page is self.CONFIRM_PAGE: return True
+ return False
+
+ def page_has_back(self, page):
+ if page is self.CONFIRM_PAGE: return True
+ elif page is self.REMOVE_PAGE: return True
+ return False
+
+ def get_back_page(self, page):
+ if page is self.CONFIRM_PAGE: return self.LIST_PAGE
+ elif page is self.REMOVE_PAGE: return self.LIST_PAGE
+
+ def validate_input(self, page, errors):
+ if page is self.LIST_PAGE:
+ if self.get_selected_domain() is not None:
+ return True
+ else:
+ errors.append("You must first select a domain.")
+ elif page is self.CONFIRM_PAGE:
+ if self.__confirm_remove.value():
+ domain = self.get_selected_domain()
+ try:
+ self.get_libvirt().undefine_domain(domain)
+ return True
+ except Exception, error:
+ errors.append("Failed to remove %s." % domain)
+ errors.append(str(error))
+ else:
+ errors.append("You must confirm undefining the domain to proceed.")
+ return False
+
+ def get_confirm_page(self, screen):
+ self.__confirm_remove = Checkbox("Check here to confirm undefining %s." % self.get_selected_domain(), 0)
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm_remove, 0, 0)
+ return [grid]
+
+ def get_remove_page(self, screen):
+ grid = Grid(1, 1)
+ grid.setField(Label("%s has been removed." % self.get_selected_domain()), 0, 0)
+ return [grid]
+
+def RemoveDomain():
+ screen = RemoveDomainConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/removehost.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/removehost.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,66 @@
+# removehost.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+
+from configscreen import *
+
+SELECT_HOST_PAGE = 1
+CONFIRM_REMOVE_PAGE = 2
+
+class RemoveHostConfigScreen(HostListConfigScreen):
+ def __init__(self):
+ HostListConfigScreen.__init__(self, "Remove Host Connection")
+
+ def get_elements_for_page(self, screen, page):
+ if page is SELECT_HOST_PAGE: return self.get_connection_list_page(screen)
+ elif page is CONFIRM_REMOVE_PAGE: return self.get_confirm_remove_page(screen)
+
+ def page_has_next(self, page):
+ return page is SELECT_HOST_PAGE and self.has_selectable_connections()
+
+ def page_has_back(self, page):
+ return page is CONFIRM_REMOVE_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_REMOVE_PAGE
+
+ def validate_input(self, page, errors):
+ if page is SELECT_HOST_PAGE: return True
+ elif page is CONFIRM_REMOVE_PAGE:
+ if self.__confirm.value():
+ return True
+ else:
+ errors.append("You must confirm removing the connection.")
+ return False
+
+ def process_input(self, page):
+ if page is CONFIRM_REMOVE_PAGE:
+ self.get_virt_manager_config().remove_connection(self.get_selected_connection())
+ self.set_finished()
+
+ def get_confirm_remove_page(self, screen):
+ self.__confirm = Checkbox("Remove this connection: %s" % self.get_selected_connection(), 0)
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm, 0, 0)
+ return [Label("Remove Host Connection"),
+ grid]
+
+def RemoveHost():
+ screen = RemoveHostConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/removepool.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/removepool.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# removepool.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_POOLS_PAGE = 1
+CONFIRM_PAGE = 2
+
+class RemoveStoragePoolConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "Remove A Storage Pool")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_POOLS_PAGE: return self.get_storage_pool_list_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ return page is LIST_POOLS_PAGE and self.has_selectable_pools()
+
+ def page_has_back(self, page):
+ return False
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def validate_input(self, page, errors):
+ if page is LIST_POOLS_PAGE:
+ if self.get_selected_pool() is not None:
+ return True
+ else:
+ errors.append("Please select a storage pool to be removed.")
+ elif page is CONFIRM_PAGE:
+ if self.__confirm.value():
+ return True
+ else:
+ errors.append("You must confirm removing a storage pool.")
+ return False
+
+ def process_input(self, page):
+ if page is CONFIRM_PAGE:
+ self.get_libvirt().destroy_storage_pool(self.get_selected_pool())
+ self.get_libvirt().undefine_storage_pool(self.get_selected_pool())
+ self.set_finished()
+
+ def get_confirm_page(self, screen):
+ self.__confirm = Checkbox("Check here to confirm deleting pool: %s" % self.get_selected_pool())
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm, 0, 0)
+ return [Label("Remove Selected Storage Pool"),
+ grid]
+
+def RemoveStoragePool():
+ screen = RemoveStoragePoolConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/removevolume.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/removevolume.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,76 @@
+# removevolume.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from createmeter import CreateMeter
+from configscreen import *
+from volumeconfig import StorageVolumeConfig
+from utils import *
+
+SELECT_POOL_PAGE = 1
+SELECT_VOLUME_PAGE = 2
+CONFIRM_PAGE = 3
+
+class RemoveVolumeConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "Add A New Storage Volume")
+ self.__config = StorageVolumeConfig()
+
+ def get_elements_for_page(self, screen, page):
+ if page is SELECT_POOL_PAGE: return self.get_storage_pool_list_page(screen)
+ elif page is SELECT_VOLUME_PAGE: return self.get_storage_volume_list_page(screen)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+
+ def page_has_next(self, page):
+ if page is SELECT_POOL_PAGE: return self.has_selectable_pools()
+ elif page is SELECT_VOLUME_PAGE: return self.has_selectable_volumes()
+ return False
+
+ def validate_input(self, page, errors):
+ if page is SELECT_POOL_PAGE: return self.get_selected_pool() is not None
+ elif page is SELECT_VOLUME_PAGE: return self.get_selected_volume() is not None
+ elif page is CONFIRM_PAGE:
+ if self.__confirm.value():
+ return True
+ else:
+ errors.append("You must confirm deleting a storage volume.")
+ return False
+
+ def process_input(self, page):
+ if page is CONFIRM_PAGE:
+ self.get_libvirt().remove_storage_volume(self.get_selected_pool(), self.get_selected_volume())
+ self.set_finished()
+
+ def page_has_back(self, page):
+ return page > SELECT_POOL_PAGE
+
+ def page_has_finish(self, page):
+ return page is CONFIRM_PAGE
+
+ def get_confirm_page(self, screen):
+ self.__confirm = Checkbox("Check here to confirm deleting volume: %s" % self.get_selected_volume())
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm, 0, 0)
+ return [Label("Remove Selected Storage Volume"),
+ grid]
+
+def RemoveStorageVolume():
+ screen = RemoveVolumeConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/setup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/setup.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,47 @@
+# setup.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from setuptools import setup, find_packages
+
+setup(name = "nodeadmin",
+ version = "1.9.3",
+ package_dir = {'nodeadmin': 'nodeadmin'},
+ packages = find_packages('.'),
+ entry_points = {
+ 'console_scripts': [
+ 'nodeadmin = nodeadmin.nodeadmin:NodeAdmin',
+ 'addvm = nodeadmin.adddomain:AddDomain',
+ 'startvm = nodeadmin.startdomain:StartDomain',
+ 'stopvm = nodeadmin.stopdomain:StopDomain',
+ 'rmvm = nodeadmin.removedomain:RemoveDomain',
+ 'migratevm = nodeadmin.migratedomain:MigradeDomain',
+ 'createuser = nodeadmin.createuser:CreateUser',
+ 'listvms = nodeadmin.listdomains:ListDomains',
+ 'definenet = nodeadmin.definenet:DefineNetwork',
+ 'createnet = nodeadmin.createnetwork:CreateNetwork',
+ 'destroynet = nodeadmin.destroynetwork:DestroyNetwork',
+ 'undefinenet = nodeadmin.undefinenetwork:UndefineNetwork',
+ 'listnets = nodeadmin.listnetworks:ListNetworks',
+ 'addpool = nodeadmin.addpool:AddStoragePool',
+ 'rmpool = nodeadmin.removepool:RemoveStoragePool',
+ 'startpool = nodeadmin.startpool:StartStoragePool',
+ 'stoppool = nodeadmin.stoppool:StopStoragePool',
+ 'addvolume = nodeadmin.addvolume:AddStorageVolume',
+ 'rmvolume = nodeadmin.removevolume:RemoveStorageVolume',
+ 'listpools = nodeadmin.listpools:ListPools']
+ })
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/startdomain.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/startdomain.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# startdomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+class StartDomainConfigScreen(DomainListConfigScreen):
+ LIST_PAGE = 1
+ START_PAGE = 2
+
+ def __init__(self):
+ DomainListConfigScreen.__init__(self, "Start A Domain")
+
+ def get_elements_for_page(self, screen, page):
+ if page is self.LIST_PAGE:
+ return self.get_domain_list_page(screen, started = False)
+ elif page is self.START_PAGE:
+ return self.get_start_domain_page(screen)
+
+ def page_has_next(self, page):
+ if page is self.LIST_PAGE: return self.has_selectable_domains()
+ return False
+
+ def page_has_back(self, page):
+ if page is self.START_PAGE: return True
+ return False
+
+ def validate_input(self, page, errors):
+ if page is self.LIST_PAGE:
+ if self.get_selected_domain() is not None:
+ domain = self.get_selected_domain()
+ try:
+ self.get_libvirt().create_domain(domain)
+ return True
+ except Exception, error:
+ errors.append("There was an error creating the domain: %s" % domain)
+ errors.append(str(error))
+ else:
+ errors.append("You must first select a domain to start.")
+
+ def get_start_domain_page(self, screen):
+ grid = Grid(1, 1)
+ grid.setField(Label("%s was successfully started." % self.get_selected_domain()), 0, 0)
+ return [grid]
+
+def StartDomain():
+ screen = StartDomainConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/startpool.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/startpool.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# startpool.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_POOLS_PAGE = 1
+FINAL_PAGE = 2
+
+class StartStoragePoolConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "Start A Storage Pool")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_POOLS_PAGE: return self.get_storage_pool_list_page(screen, created = False)
+ elif page is FINAL_PAGE: return self.get_final_page(screen)
+
+ def page_has_next(self, page):
+ return page is LIST_POOLS_PAGE and self.has_selectable_pools()
+
+ def page_has_back(self, page):
+ return False
+
+ def page_has_finish(self, page):
+ return page is FINAL_PAGE
+
+ def validate_input(self, page, errors):
+ if page is LIST_POOLS_PAGE:
+ if self.get_selected_pool() is not None:
+ return True
+ else:
+ errors.append("Please select a storage pool to be started.")
+ return False
+
+ def process_input(self, page):
+ if page is LIST_POOLS_PAGE:
+ self.get_libvirt().create_storage_pool(self.get_selected_pool())
+ self.set_finished()
+
+ def get_final_page(self, screen):
+ return [Label("Storage pool started: %s" % self.get_selected_pool())]
+
+def StartStoragePool():
+ screen = StartStoragePoolConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/stopdomain.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/stopdomain.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# stopdomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+class StopDomainConfigScreen(DomainListConfigScreen):
+ LIST_PAGE = 1
+ STOP_PAGE = 2
+
+ def __init__(self):
+ DomainListConfigScreen.__init__(self, "Stop A Domain")
+
+ def get_elements_for_page(self, screen, page):
+ if page is self.LIST_PAGE:
+ return self.get_domain_list_page(screen, defined = False)
+ elif page is self.STOP_PAGE:
+ return self.get_stop_page(screen)
+
+ def page_has_next(self, page):
+ if page is self.LIST_PAGE: return self.has_selectable_domains()
+ return False
+
+ def page_has_back(self, page):
+ if page is self.STOP_PAGE: return True
+ return False
+
+ def validate_input(self, page, errors):
+ if page is self.LIST_PAGE:
+ if self.get_selected_domain() is not None:
+ domain = self.get_selected_domain()
+ try:
+ self.get_libvirt().destroy_domain(domain)
+ return True
+ except Exception, error:
+ errors.append("There was an error stop the domain: %s" % domain)
+ errors.append(str(error))
+ else:
+ errors.append("You must first select a domain to stop.")
+ return False
+
+ def get_stop_page(self, screen):
+ grid = Grid(1, 1)
+ grid.setField(Label("%s was successfully stoped." % self.get_selected_domain()), 0, 0)
+ return [grid]
+
+def StopDomain():
+ screen = StopDomainConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/stoppool.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/stoppool.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# stoppool.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_POOLS_PAGE = 1
+FINAL_PAGE = 2
+
+class StopStoragePoolConfigScreen(StorageListConfigScreen):
+ def __init__(self):
+ StorageListConfigScreen.__init__(self, "Stop A Storage Pool")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_POOLS_PAGE: return self.get_storage_pool_list_page(screen, defined = False)
+ elif page is FINAL_PAGE: return self.get_final_page(screen)
+
+ def page_has_next(self, page):
+ return page is LIST_POOLS_PAGE and self.has_selectable_pools()
+
+ def page_has_back(self, page):
+ return False
+
+ def page_has_finish(self, page):
+ return page is FINAL_PAGE
+
+ def validate_input(self, page, errors):
+ if page is LIST_POOLS_PAGE:
+ if self.get_selected_pool() is not None:
+ return True
+ else:
+ errors.append("Please select a storage pool to be stopped.")
+ return False
+
+ def process_input(self, page):
+ if page is LIST_POOLS_PAGE:
+ self.get_libvirt().destroy_storage_pool(self.get_selected_pool())
+ self.set_finished()
+
+ def get_final_page(self, screen):
+ return [Label("Storage pool stopped: %s" % self.get_selected_pool())]
+
+def StopStoragePool():
+ screen = StopStoragePoolConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/storagemenu.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/storagemenu.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,63 @@
+# storagemenu.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+import traceback
+
+from menuscreen import MenuScreen
+from addpool import AddStoragePool
+from startpool import StartStoragePool
+from stoppool import StopStoragePool
+from removepool import RemoveStoragePool
+from addvolume import AddStorageVolume
+from removevolume import RemoveStorageVolume
+from listpools import ListStoragePools
+
+ADD_POOL = 1
+START_POOL = 2
+STOP_POOL = 3
+REMOVE_POOL = 4
+ADD_VOLUME = 5
+REMOVE_VOLUME = 6
+LIST_POOLS = 7
+
+class StoragePoolMenuScreen(MenuScreen):
+ def __init__(self):
+ MenuScreen.__init__(self, "Storage Pool Administration")
+
+ def get_menu_items(self):
+ return (("Add A Storage Pool", ADD_POOL),
+ ("Start A Storage Pool", START_POOL),
+ ("Stop A Storage Pool", STOP_POOL),
+ ("Remove A Storage Pool", REMOVE_POOL),
+ ("Add A Storage Volume", ADD_VOLUME),
+ ("Remove A Storage Volume", REMOVE_VOLUME),
+ ("List Storage Pools", LIST_POOLS))
+
+ def handle_selection(self, item):
+ if item is ADD_POOL: AddStoragePool()
+ elif item is START_POOL: StartStoragePool()
+ elif item is STOP_POOL: StopStoragePool()
+ elif item is REMOVE_POOL: RemoveStoragePool()
+ elif item is ADD_VOLUME: AddStorageVolume()
+ elif item is REMOVE_VOLUME: RemoveStorageVolume()
+ elif item is LIST_POOLS: ListStoragePools()
+
+def StoragePoolMenu():
+ screen = StoragePoolMenuScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/undefinenetwork.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/undefinenetwork.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+#
+# undefinenetwork.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from configscreen import *
+
+LIST_PAGE = 1
+CONFIRM_PAGE = 2
+UNDEFINE_PAGE = 3
+
+class UndefineNetworkConfigScreen(NetworkListConfigScreen):
+ def __init__(self):
+ NetworkListConfigScreen.__init__(self, "Undefine A Network")
+
+ def get_elements_for_page(self, screen, page):
+ if page is LIST_PAGE: return self.get_network_list_page(screen, created = False)
+ elif page is CONFIRM_PAGE: return self.get_confirm_page(screen)
+ elif page is UNDEFINE_PAGE: return self.get_undefine_network_page(screen)
+
+ def process_input(self, page, errors):
+ if page is LIST_PAGE:
+ network = self.get_selected_network()
+ self.get_libvirt().undefine_network(network)
+ return True
+
+ def page_has_next(self, page):
+ if page is LIST_PAGE: return self.has_selectable_networks()
+ if page is CONFIRM_PAGE: return True
+ return False
+
+ def page_has_back(self, page):
+ if page is CONFIRM_PAGE: return True
+ if page is UNDEFINE_PAGE: return True
+ return False
+
+ def get_back_page(self, page):
+ if page is CONFIRM_PAGE: return LIST_PAGE
+ elif page is UNDEFINE_PAGE: return LIST_PAGE
+
+ def validate_input(self, page, errors):
+ if page is LIST_PAGE: return True
+ elif page is CONFIRM_PAGE:
+ if self.__confirm_undefine.value():
+ return True
+ else:
+ errors.append("You must confirm undefining %s." % self.get_selected_network())
+ elif page is UNDEFINE_PAGE: return True
+ return False
+
+ def process_input(self, page):
+ if page is LIST_PAGE: return True
+ elif page is CONFIRM_PAGE:
+ network = self.get_selected_network()
+ self.get_libvirt().undefine_network(network)
+ return True
+ elif page is UNDEFINE_PAGE: return True
+ return False
+
+ def get_confirm_page(self, screen):
+ self.__confirm_undefine = Checkbox("Check here to confirm undefining %s." % self.get_selected_network(), 0)
+ grid = Grid(1, 1)
+ grid.setField(self.__confirm_undefine, 0, 0)
+ return [grid]
+
+ def get_undefine_network_page(self, screen):
+ return [Label("Network Is Undefined"),
+ Label("Network has been undefined: %s" % self.get_selected_network())]
+
+def UndefineNetwork():
+ screen = UndefineNetworkConfigScreen()
+ screen.start()
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/userworker.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/userworker.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,37 @@
+# userworker.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import libuser
+
+class UserWorker:
+ '''Provides APIs for creating, modifying and deleting user accounts.'''
+ def __init__(self):
+ self.__admin = libuser.admin()
+
+ def create_user(self, username, password, other_group):
+ '''Creates a new user account with the provides username,
+ password. The user is also added to the optional group
+ if one is specified.'''
+ user = self.__admin.initUser(username)
+ user.set('pw_passwd', password)
+ self.__admin.addUser(user)
+ if other_group is not None:
+ group = self.__admin.lookupGroupByName(other_group)
+ if group is None: raise Exception("Invalid group specified: %s" % other_group)
+ user.add('pw_gid', group.get('pw_gid')[0])
+ self.__admin.modifyUser(user)
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/utils.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/utils.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,44 @@
+# definedomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import logging
+import re
+
+logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(levelname)-8s %(message)s',
+ datefmt='%a, %d %b %Y %H:%M:%S',
+ filename='/var/log/ovirt-nodeadmin.log',
+ filemode='w')
+
+def string_is_not_blank(value):
+ if len(value) > 0: return True
+ return False
+
+def string_has_no_spaces(value):
+ if re.match("^[a-zA-Z0-9_]*$", value):
+ return True
+ return False
+
+def size_as_mb_or_gb(size):
+ '''Takes a size value in bytes and returns it as either a
+ value in megabytes or gigabytes.'''
+ if size / 1024.0**3 < 1.0:
+ result = "%0.2f MB" % (size / 1024.0**2)
+ else:
+ result = "%0.2f GB" % (size / 1024.0**3)
+ return result
diff -r a6184d2d4052 -r 23f2fc0a3cb2 src/virtManagerTui/volumeconfig.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/virtManagerTui/volumeconfig.py Mon Aug 16 10:06:35 2010 -0400
@@ -0,0 +1,83 @@
+# volumeconfig.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+import virtinst
+from virtinst import Storage
+
+class StorageVolumeConfig:
+ def __init__(self):
+ self.__pool = None
+ self.__name = ""
+ self.__formats = None
+ self.__format = None
+ self.__max_capacity = 10000
+ self.__allocation = 0
+
+ def set_pool(self, pool):
+ self.__pool = pool
+ self.__formats = None
+ self.__pool_type = virtinst.util.get_xml_path(self.__pool.XMLDesc(0), '/pool/@type')
+ self.__volume_class = Storage.StoragePool.get_volume_for_pool(self.__pool_type)
+
+ def get_pool(self):
+ return self.__pool
+
+ def create_volume(self):
+ volume = self.__volume_class(name = self.__name + ".img",
+ allocation = self.__allocation * 1024**2,
+ capacity = self.__max_capacity * 1024**2,
+ pool = self.__pool)
+ volume.pool = self.__pool
+ if self.needs_format():
+ volume.format = self.__format
+ return volume
+
+ def set_name(self, name):
+ self.__name = name
+
+ def get_name(self):
+ return self.__name
+
+ def needs_format(self):
+ if self.__pool.__dict__.keys().count("get_formats_for_pool") > 0:
+ return self.__pool.get_formats_for_pool() is not 0
+ else:
+ return False
+
+ def get_formats_for_pool(self):
+ if self.__formats is None:
+ self.__formats = self.__volume_class.formats
+ return self.__formats
+
+ def set_format(self, format):
+ self.__format = format
+
+ def get_format(self):
+ return self.__format
+
+ def set_max_capacity(self, capacity):
+ self.__max_capacity = capacity
+
+ def get_max_capacity(self):
+ return self.__max_capacity
+
+ def set_allocation(self, allocation):
+ self.__allocation = allocation
+
+ def get_allocation(self):
+ return self.__allocation
More information about the virt-tools-list
mailing list