Add code for virt-manager TUI from OVirt node project

This code is taken from the ovirt node project. Overtime the plan is to share
lots of code between the GUI and TUI. This is step 1 though.

Code can be invoked with:

cd src/virtManagerTui
python nodeadmin.py

Additional requirements beyond plain virt-manager are a system installed IPy
and newt-python (or whatever package provides the 'snack' module)
This commit is contained in:
Darryl L. Pierce 2010-08-19 11:26:07 -04:00
parent d5a1262ee6
commit b000c87302
42 changed files with 4384 additions and 0 deletions

View File

@ -0,0 +1,19 @@
# __init__.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,512 @@
#!/usr/bin/env python
#
# adddomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,135 @@
# addhost.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,187 @@
# addstorage.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,178 @@
# addvolume.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,60 @@
# changehost.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,295 @@
# configscreen.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,30 @@
# createmeter.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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)

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
#
# createnetwork.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,106 @@
#!/usr/bin/env python
#
# createuser.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,257 @@
# definenet.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,56 @@
#!/usr/bin/env python
#
# destroynetwork.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,224 @@
# domainconfig.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,45 @@
# halworker.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,29 @@
# hostconnect.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,46 @@
# hostmenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,461 @@
# libvirtworker.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,68 @@
#!/usr/bin/env python
#
# listdomains.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,55 @@
# listnetworks.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,64 @@
# listpools.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,55 @@
# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,57 @@
# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
#
# migratedomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,58 @@
# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,99 @@
# networkconfig.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
#
# node-admin - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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())

View File

@ -0,0 +1,67 @@
# mainmenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,145 @@
# poolconfig.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
#
# removedomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,66 @@
# removehost.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python
#
# removepool.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,76 @@
# removevolume.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,47 @@
# setup.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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']
})

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
#
# startdomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python
#
# startpool.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,66 @@
#!/usr/bin/env python
#
# stopdomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,62 @@
#!/usr/bin/env python
#
# stoppool.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,63 @@
# storagemenu.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,88 @@
#!/usr/bin/env python
#
# undefinenetwork.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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()

View File

@ -0,0 +1,37 @@
# userworker.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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)

View File

@ -0,0 +1,44 @@
# definedomain.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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

View File

@ -0,0 +1,83 @@
# volumeconfig.py - Copyright (C) 2009 Red Hat, Inc.
# Written by Darryl L. Pierce <dpierce@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