Package virtualization :: Module domain_directory
[hide private]
[frames] | no frames]

Source Code for Module virtualization.domain_directory

  1  # 
  2  # Copyright (c) 2008--2013 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15   
 16  import binascii 
 17  import os 
 18  import sys 
 19   
 20  try: 
 21      import libvirt 
 22  except ImportError: 
 23      # There might not be a libvirt; we won't die here so that other modules 
 24      # who import us can exit gracefully. 
 25      libvirt = None 
 26   
 27  from rhn.i18n import sstr 
 28   
 29  from virtualization.domain_config import DomainConfig 
 30  from virtualization.errors        import VirtualizationException 
 31  from virtualization.util          import dehyphenize_uuid, \ 
 32                                           hyphenize_uuid,   \ 
 33                                           is_host_uuid 
 34   
 35  ############################################################################### 
 36  # Constants 
 37  ############################################################################### 
 38   
 39  CONFIG_DIR = '/etc/sysconfig/rhn/virt' 
 40  STANDARD_CONFIG_TEMPLATE = """ 
 41      <domain type='xen'> 
 42          <name>%(name)s</name> 
 43          <bootloader>/usr/bin/pygrub</bootloader> 
 44          <memory>%(mem_kb)s</memory> 
 45          <vcpu>%(vcpus)s</vcpu> 
 46          <uuid>%(uuid)s</uuid> 
 47          <on_reboot>restart</on_reboot> 
 48          <on_poweroff>destroy</on_poweroff> 
 49          <on_crash>preserve</on_crash> 
 50          <devices> 
 51              <disk type='file'> 
 52                  <source file='%(disk)s'/> 
 53                  <target dev='xvda'/> 
 54              </disk> 
 55              <interface type='bridge'> 
 56                  <source bridge='xenbr0'/> 
 57                  <mac address='%(mac)s'/> 
 58                  <script path='/etc/xen/scripts/vif-bridge'/> 
 59              </interface> 
 60          </devices> 
 61  </domain> 
 62  """ 
 63   
 64  ############################################################################### 
 65  # Classes 
 66  ############################################################################### 
 67   
68 -class DomainDirectory:
69
70 - def __init__(self):
71 self.__path = CONFIG_DIR 72 self.conn = libvirt.openReadOnly(None) 73 if not self.conn: 74 raise VirtualizationException("Failed to open connection to hypervisor.")
75
76 - def get_config_path(self, uuid):
77 cfg_filename = "%s.xml" % uuid 78 cfg_pathname = os.path.join(self.__path, cfg_filename) 79 return cfg_pathname
80
81 - def is_known_config(self, uuid):
82 """ 83 Returns true if a config for the given uuid is saved in the directory. 84 """ 85 path = self.get_config_path(uuid) 86 return os.path.exists(path)
87
88 - def load_config(self, uuid):
89 """ 90 This function loads a domain's configuration by its UUID. A 91 DomainConfig object is returned. 92 """ 93 return DomainConfig(self.__path, uuid)
94
95 - def create_standard_config(self, uuid, name, mem_kb, vcpus, disk, mac):
96 # First, populate the XML with the appropriate values. 97 boot_params = { 'name' : name, 98 'mem_kb' : mem_kb, 99 'vcpus' : vcpus, 100 'uuid' : hyphenize_uuid(uuid), 101 'disk' : disk, 102 'mac' : mac } 103 104 xml = STANDARD_CONFIG_TEMPLATE % boot_params 105 106 self.__write_xml_file(uuid, xml)
107
108 - def save_unknown_domain_configs(self, domain_uuids):
109 """ 110 This function saves the configuration for any domains whose UUIDs are 111 passed in the domain_uuids list. If the UUID is already known, it is 112 skipped. 113 """ 114 115 for uuid in domain_uuids: 116 117 uuid = sstr(uuid) 118 # If we already have a config for this uuid, skip it. Also, don't 119 # try to figure out a config for a host UUID. 120 if not is_host_uuid(uuid) and not self.is_known_config(uuid): 121 122 # The UUID is a formatted string. Turn it back into a number, 123 # since that's what libvirt wants. 124 dehyphenized_uuid = dehyphenize_uuid(uuid) 125 uuid_as_num = binascii.unhexlify(dehyphenized_uuid) 126 127 # Lookup the domain by its uuid. 128 try: 129 domain = self.conn.lookupByUUID(uuid_as_num) 130 except libvirt.libvirtError: 131 lve = sys.exc_info()[1] 132 raise VirtualizationException("Failed to obtain handle to domain %s: %s" % (uuid, repr(lve))) 133 134 # Now grab the XML description of the configuration. 135 xml = domain.XMLDesc(0) 136 137 # Write the xml out to a file so that we can load it into our 138 # abstract DomainConfig object and manipulate it easily. 139 cfg_file_path = self.__write_xml_file(uuid, xml) 140 new_config = DomainConfig(self.__path, uuid) 141 142 # Don't record the config this time if the domain is 143 # installing; we don't want to restart the domain later and 144 # make it re-install itself. 145 if not new_config.isInstallerConfig(): 146 147 # Now we'll reformat the configuration object so that it's 148 # valid the next time this domain runs.. 149 self.__fixup_config_for_restart(new_config) 150 151 # The config is now prepared. Save it and move on to the 152 # next uuid. 153 new_config.save() 154 155 else: 156 # Remove the config file we just wrote. 157 os.unlink(cfg_file_path)
158
159 - def __fixup_config_for_restart(self, config):
160 """ 161 This function edits the given configuration so that it can be used in 162 subsequent calls to libvirt's createLinux call. Specifically, the 163 following modifications are made: 164 165 - Remove the "id" attribute from the <domain> tag. The "id" is 166 whatever the hypervisor wants to assign to it, so we should not 167 try to assign it explicitly. 168 169 - Determine whether the config contains an <os> section. 170 - If it does, check whether the kernel and the initrd files 171 it refers to actually exist on disk. 172 - If so, do nothing. 173 - If not, remove the entire <os> section and insert a 174 <bootloader> section if one does not yet exist. These 175 files might not exist if the instance was started by xm 176 using a bootloader such as pygrub, which makes temporary 177 copies of the kernel & initrd and then removes them after 178 starting the instance. 179 - If it does not, ensure there is a <bootloader> section or 180 add one if needed. 181 """ 182 # Remove the domain ID from the XML. This is a runtime value that 183 # should not be assigned statically. 184 if config.hasConfigItem(DomainConfig.DOMAIN_ID): 185 config.removeConfigItem(DomainConfig.DOMAIN_ID) 186 187 if self.conn.getType() == 'QEMU': 188 # Dont worry about bootloader if its kvm 189 return 190 191 boot_images_exist = 0 192 193 if config.hasConfigItem(DomainConfig.KERNEL_PATH) and \ 194 config.hasConfigItem(DomainConfig.RAMDISK_PATH): 195 196 kernel_path = config.getConfigItem(DomainConfig.KERNEL_PATH) 197 ramdisk_path = config.getConfigItem(DomainConfig.KERNEL_PATH) 198 199 if os.path.exists(kernel_path) and os.path.exists(ramdisk_path): 200 boot_images_exist = 1 201 202 # If we've determined that the referenced boot images do not exist, 203 # remove the OS section and insert a bootloader piece. 204 if not boot_images_exist: 205 if config.hasConfigItem(DomainConfig.OS): 206 config.removeConfigItem(DomainConfig.OS) 207 208 if not config.hasConfigItem(DomainConfig.BOOTLOADER): 209 config.setConfigItem(DomainConfig.BOOTLOADER, "/usr/bin/pygrub")
210 211
212 - def __write_xml_file(self, uuid, xml):
213 cfg_pathname = self.get_config_path(uuid) 214 cfg_file = open(cfg_pathname, "w") 215 cfg_file.write(xml.strip()) 216 cfg_file.close() 217 218 return cfg_pathname
219