Module image
[hide private]
[frames] | no frames]

Source Code for Module image

  1  #!/usr/bin/python 
  2  import base64 
  3  try: 
  4      # python2 
  5      import ConfigParser 
  6  except ImportError: 
  7      # python3 
  8      import configparser as ConfigParser 
  9  import itertools 
 10  import os 
 11  import platform 
 12  import pycurl 
 13  import sys 
 14   
 15  import virtualization.support as virt_support 
 16  from virtualization.util import generate_uuid 
 17  from virtualization.errors import VirtualizationException 
 18  from up2date_client import up2dateLog 
 19   
 20  log = up2dateLog.initLog() 
 21   
 22  config = ConfigParser.ConfigParser({ 
 23      "IMAGE_BASE_PATH"      : "/var/lib/libvirt/images/", 
 24      "IMAGE_CFG_TEMPLATE"   : "/etc/sysconfig/rhn/kvm-template.xml", 
 25      "PRE_SCRIPT"           : "", 
 26  }) 
 27  config.read('/etc/sysconfig/rhn/image.cfg') 
 28  IMAGE_BASE_PATH    = config.get("global", "IMAGE_BASE_PATH") 
 29  IMAGE_CFG_TEMPLATE = config.get("global", "IMAGE_CFG_TEMPLATE") 
 30  PRE_SCRIPT         = config.get("global", "PRE_SCRIPT") 
 31   
 32  # mark this module as acceptable 
 33  __rhnexport__ = [ 
 34      'deploy' 
 35  ] 
 36   
37 -def _download_file(target_filename, server_url, proxy_settings):
38 """Download file from a URL to given filename using given proxy settings.""" 39 log.log_debug("downloading %s" % server_url) 40 41 # get the file via pycurl 42 c = pycurl.Curl() 43 c.setopt(pycurl.URL, server_url) 44 45 # proxy_settings: { proxyURL : http://myproxy.site:3128 46 # proxyUser : user 47 # proxyPass : s3cr3t } 48 # proxyUser and proxyPass are optional 49 if "proxyURL" in proxy_settings and proxy_settings["proxyURL"] is not None and proxy_settings["proxyURL"] != "": 50 server = proxy_settings["proxyURL"] 51 c.setopt(pycurl.PROXY, server ) 52 if "proxyUser" in proxy_settings and proxy_settings["proxyUser"] is not None and proxy_settings["proxyUser"] != "": 53 user = proxy_settings["proxyUser"] 54 password = base64.b64decode(proxy_settings["proxyPass"]) 55 c.setopt(pycurl.PROXYUSERPWD, "%s:%s" % (user, password)) 56 # default IMAGE_BASE_PATH is /var/lib/libvirt/images 57 file_path = "/%s/%s" % (IMAGE_BASE_PATH, target_filename) 58 f = open(file_path, 'w') 59 c.setopt(pycurl.FOLLOWLOCATION, 1) 60 c.setopt(pycurl.WRITEFUNCTION, f.write) 61 c.setopt(pycurl.SSL_VERIFYPEER, 0) 62 c.perform() 63 log.log_debug("curl got HTTP code: %s" % c.getinfo(pycurl.HTTP_CODE)) 64 f.close() 65 return c.getinfo(pycurl.HTTP_CODE)
66
67 -def _connect_to_hypervisor():
68 """Connect to the hypervisor.""" 69 # First, attempt to import libvirt. If we don't have that, we can't do 70 # much else. 71 try: 72 import libvirt 73 except ImportError as ie: 74 raise VirtualizationException("Unable to locate libvirt: %s" % str(ie)) 75 76 # Attempt to connect to the hypervisor. 77 try: 78 connection = libvirt.open(None) 79 except Exception as e: 80 raise VirtualizationException("Could not connect to hypervisor: %s" % str(e)) 81 82 return connection
83
84 -def _file_exists(name):
85 return os.path.exists(name)
86
87 -def _domain_exists(dom, connection):
88 try: 89 connection.lookupByName(dom) 90 except Exception: 91 log.log_debug("domain %s does not exist" % dom) 92 return False 93 log.log_debug("domain %s exists" % dom) 94 return True
95
96 -def _generate_xml(params):
97 """Populate the variables in the XML template file.""" 98 if PRE_SCRIPT != "": 99 log.log_debug("running image pre-script %s" % PRE_SCRIPT) 100 os.system(PRE_SCRIPT) 101 102 if os.path.isfile(IMAGE_CFG_TEMPLATE): 103 f = open(IMAGE_CFG_TEMPLATE, 'r') 104 CREATE_TEMPLATE = f.read() 105 f.close() 106 107 created_xml = CREATE_TEMPLATE % params 108 log.log_debug("libvirt XML: %s" % created_xml) 109 return created_xml
110 111 # Download and start a new image given by the following parameters: 112 # 113 # downloadURL : http://download.suse.de/install/SLE-15-JeOS-RC2/SLES15-JeOS.x86_64-15.0-kvm-and-xen-RC2.qcow2 114 # proxySettings : { proxyURL : http://myproxy.site:3128 115 # proxyUser : user 116 # proxyPass : s3cr3t } 117 # memKB : 524288 118 # vCPUs : 1 119 # domainName : virt_test_machine 120 # virtBridge : br0
121 -def deploy(params, extra_params="", cache_only=None):
122 """Download and start a new image.""" 123 124 image_filename = params["downloadURL"].split('/')[-1] 125 domain_name, image_extension = os.path.splitext(image_filename) 126 if not image_extension or image_extension != ".qcow2": 127 return (1, "image type is not qcow2: %s" % image_filename, {}) 128 image_arch = platform.machine() or 'x86_64' 129 130 try: 131 connection = _connect_to_hypervisor() 132 except Exception as e: 133 return (1, "%s" % e, {}) 134 135 # If we got an explicit domain name then use it and update the filename 136 if "domainName" in params and params["domainName"] != "": 137 domain_name = params["domainName"] 138 image_filename = domain_name + image_extension 139 140 # If domain or file exists try to find a free name for both 141 if _domain_exists(domain_name, connection) or _file_exists("%s/%s" % (IMAGE_BASE_PATH, image_filename)): 142 for i in itertools.count(1): 143 new_domain_name = ("%s-%i" % (domain_name, i)) 144 image_filename = new_domain_name + image_extension 145 if not _domain_exists(new_domain_name, connection) and not _file_exists("%s/%s" % (IMAGE_BASE_PATH, image_filename)): 146 log.log_debug("free domain and matching filename found") 147 domain_name = new_domain_name 148 break 149 150 log.log_debug("filename=%s domain=%s arch=%s" % (image_filename, domain_name, image_arch)) 151 152 if not domain_name or image_arch not in ['x86_64', 'i686', 'ppc64le', 's390x']: 153 log.log_debug("invalid domain name or arch") 154 return (1, "invalid domain name or arch: domain=%s arch=%s" % (domain_name, image_arch), {}) 155 156 http_response_code = -1 157 try: 158 http_response_code = _download_file(image_filename, params["downloadURL"], params["proxySettings"]) 159 if not _file_exists("%s/%s" % (IMAGE_BASE_PATH, image_filename)): 160 log.log_debug("downloading image file failed, HTTP return code: %s" % http_response_code) 161 return (1, "downloading image file failed: %s/%s (%s)" % (IMAGE_BASE_PATH, image_filename, http_response_code), {}) 162 except Exception as e: 163 return (1, "getting the image failed with: %s" % e, {}) 164 if cache_only: 165 return (0, "image fetched and cached for later deployment", {}) 166 167 image_path = "%s/%s" % (IMAGE_BASE_PATH, image_filename) 168 if not os.path.exists(image_path): 169 return (1, "image not found at %s" % image_path, {}) 170 log.log_debug("working on image in %s" % image_path) 171 172 create_params = { 'name' : domain_name, 173 'arch' : image_arch, 174 'extra' : extra_params, 175 'mem_kb' : params["memKB"], 176 'vcpus' : params["vCPUs"], 177 'uuid' : generate_uuid(), 178 'disk' : image_path, 179 'imageType' : 'qcow2', 180 'virtBridge' : params["virtBridge"], 181 } 182 create_xml = _generate_xml(create_params) 183 domain = None 184 try: 185 domain = connection.defineXML(create_xml) 186 except Exception as e: 187 return (1, "failed to pass XML to libvirt: %s" % e, {}) 188 189 domain.create() 190 virt_support.refresh() 191 192 return (0, "image '%s' deployed and started" % domain_name, {})
193 194 # just for testing 195 if __name__ == "__main__": 196 # test code 197 log.log_debug("actions/image.py called") 198 print("You can not run this module by itself") 199 sys.exit(-1) 200