def provision(self): if not self.supported(): raise RuntimeError( _('Unsupported distribution for ' 'postgresql proisioning')) self._initDbIfRequired() self.logger.info( _("Creating PostgreSQL '{database}' database").format( database=self.environment[self._dbenvkeys['database']], )) localtransaction = transaction.Transaction() try: localtransaction.prepare() self._setPgHbaLocalPeer(transaction=localtransaction, ) self._restart() with AlternateUser(user=self.environment[ oengcommcons.SystemEnv.USER_POSTGRES], ): usockenv = { self._dbenvkeys['host']: '', # usock self._dbenvkeys['port']: '', self._dbenvkeys['secured']: False, self._dbenvkeys['hostValidation']: False, self._dbenvkeys['user']: '******', self._dbenvkeys['password']: '', self._dbenvkeys['database']: 'template1', } self._waitForDatabase(environment=usockenv, ) existing = self._setDatabaseResources(environment=usockenv, ) self._performDatabase( environment=usockenv, op=('alter' if existing else 'create'), ) finally: # restore everything localtransaction.abort() self.logger.info(_('Configuring PostgreSQL')) with transaction.Transaction() as localtransaction: self._updatePostgresConf( transaction=localtransaction, maxconn=self.environment[ oengcommcons.ProvisioningEnv.POSTGRES_MAX_CONN], listenaddr=self.environment[ oengcommcons.ProvisioningEnv.POSTGRES_LISTEN_ADDRESS], ) self._addPgHbaDatabaseAccess(transaction=localtransaction, ) self.services.startup( name=self.environment[ oengcommcons.ProvisioningEnv.POSTGRES_SERVICE], state=True, ) self._restart() self._waitForDatabase()
def _init(self): self._internalPackageTransaction = transaction.Transaction() self._mainTransaction = transaction.Transaction() self.environment[ constants.CoreEnv. INTERNAL_PACKAGES_TRANSACTION] = self._internalPackageTransaction self.environment[ constants.CoreEnv.MAIN_TRANSACTION] = self._mainTransaction self.environment[constants.CoreEnv.MODIFIED_FILES] = [] self.context.registerNotification(self._notify)
def provision(self): if not self.supported(): raise RuntimeError( _('Unsupported distribution for ' 'postgresql proisioning')) self._initDbIfRequired() self.logger.info( _("Creating PostgreSQL '{database}' database").format( database=_ind_env(self, DEK.DATABASE), )) localtransaction = transaction.Transaction() try: localtransaction.prepare() self._setPgHbaLocalPeer(transaction=localtransaction, ) self.restartPG() with AlternateUser(user=self.environment[ oengcommcons.SystemEnv.USER_POSTGRES], ): usockenv = { self._dbenvkeys[DEK.HOST]: '', # usock self._dbenvkeys[DEK.PORT]: '', self._dbenvkeys[DEK.SECURED]: False, self._dbenvkeys[DEK.HOST_VALIDATION]: False, self._dbenvkeys[DEK.USER]: 'postgres', self._dbenvkeys[DEK.PASSWORD]: '', self._dbenvkeys[DEK.DATABASE]: 'template1', } self._waitForDatabase(environment=usockenv, ) existing = self._setDatabaseResources(environment=usockenv, ) self._performDatabase( environment=usockenv, op=('alter' if existing else 'create'), ) finally: # restore everything localtransaction.abort() self.logger.info(_('Configuring PostgreSQL')) with transaction.Transaction() as localtransaction: self._updatePostgresConf(transaction=localtransaction, ) self.addPgHbaDatabaseAccess(transaction=localtransaction, ) self.services.startup( name=self.environment[ oengcommcons.ProvisioningEnv.POSTGRES_SERVICE], state=True, ) self.restartPG() self._waitForDatabase() # We should install the UUID extension when a new db is created self.installUuidOsspExtension()
def _configure_glusterfs_service(self): """ @see: http://www.ovirt.org/Features/ Self_Hosted_Engine_Hyper_Converged_Gluster_Support #Config_files_changes """ content = [] with open(ohostedcons.FileLocations.GLUSTERD_VOL, 'r') as f: for line in f.read().splitlines(): if line.find('rpc-auth-allow-insecure') != -1: continue elif line.find('base-port') != -1: continue elif line.find('end-volume') == 0: content.append(' option rpc-auth-allow-insecure on') content.append(' option base-port 49217') content.append(line) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.GLUSTERD_VOL, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], ), )
def _misc(self): self.logger.info(_('Configuring VDSM')) if not os.path.exists(ohostedcons.FileLocations.VDSM_CONF): self.logger.warning( _( 'VDSM configuration file not found: ' 'creating a new configuration file' ) ) for section in ('irs', 'vars'): if not self.config.has_section(section): self.config.add_section(section) self.config.set( 'vars', 'default_bridge', self.environment[ohostedcons.NetworkEnv.BRIDGE_NAME] ) f = StringIO.StringIO() try: self.config.write(f) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.VDSM_CONF, content=f.getvalue(), modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ), ) finally: f.close()
def _misc(self): if self.environment.get(oprovisioncons.ConfigEnv.PROVISION_DB): self._provisioning.provision() if self.environment.get(oprovisioncons.ConfigEnv.PROVISION_USER): self._provisioning.createUser() if self._provisioning.databaseRenamed: osetuputil.addExitCode( environment=self.environment, code=( osetupcons.Const. EXIT_CODE_PROVISIONING_EXISTING_RESOURCES_FOUND ) ) raise RuntimeError( _( 'Existing resources found, new ones created: \n' 'database {database} user {user}' ).format( database=self.environment[ oprovisioncons.ProvDBEnv.DATABASE ], user=self.environment[ oprovisioncons.ProvDBEnv.USER ], ) ) if self.environment.get(oprovisioncons.ConfigEnv.ADD_TO_PG_HBA): with transaction.Transaction() as localtransaction: self._provisioning.addPgHbaDatabaseAccess( transaction=localtransaction, ) if self.environment.get(oprovisioncons.ConfigEnv.GRANT_READONLY): self._provisioning.grantReadOnlyAccessToUser() self._provisioning.restartPG()
def _getSSHkey(self): self.logger.debug('Acquiring SSH key from the engine') with contextlib.closing( urllib2.urlopen( 'http://{fqdn}/engine.ssh.key.txt'.format( fqdn=self.environment[ ohostedcons.NetworkEnv.OVIRT_HOSTED_ENGINE_FQDN ] ) ) ) as urlObj: authorized_keys_line = urlObj.read() if authorized_keys_line: self.logger.debug(authorized_keys_line) authorized_keys_file = os.path.join( os.path.expanduser('~root'), '.ssh', 'authorized_keys' ) content = [] if os.path.exists(authorized_keys_file): with open(authorized_keys_file, 'r') as f: content = f.read().splitlines() if authorized_keys_line not in content: content.append(authorized_keys_line) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=authorized_keys_file, content=content, mode=0o600, owner='root', enforcePermissions=True, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ) ) if self._selinux_enabled: path = os.path.join( os.path.expanduser('~root'), '.ssh' ) rc, stdout, stderr = self.execute( ( self.command.get('restorecon'), '-r', path ) ) if rc != 0: self.logger.error( _('Failed to refresh SELINUX context for {path}').format( path=path ) )
def _miscUpgrade(self): self.logger.info(_('Upgrading CA')) # # LEGACY NOTE # Since 3.0 and maybe before the method of # allowing user to override AIA was to explict # edit files. Until we rewrite the entire PKI # we must preserve this approach. # The template may change over time, so regenerate. # aia = None template = oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE[ :-len('.in') ] if os.path.exists(template): with open(template) as f: PREFIX = 'caIssuers;URI:' for l in f.readlines(): if l.startswith('authorityInfoAccess'): aia = l[l.find(PREFIX)+len(PREFIX):] break uninstall_files = [] self._setupUninstall(uninstall_files) if aia is not None: localtransaction = transaction.Transaction() with localtransaction: for name in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_TEMPLATE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE, ): localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.in')], content=outil.processTemplate( name, { '@AIA@': aia, } ), modifiedList=uninstall_files, ), ) localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.template.in')] + '.conf', content=outil.processTemplate( name, { '@AIA@': aia, } ), modifiedList=uninstall_files, ), )
def createUser(self): if not self.supported(): raise RuntimeError( _( 'Unsupported distribution for ' 'postgresql proisioning' ) ) self._initDbIfRequired() localtransaction = transaction.Transaction() try: localtransaction.prepare() self._setPgHbaLocalPeer( transaction=localtransaction, ) self._restart() with AlternateUser( user=self.environment[ oengcommcons.SystemEnv.USER_POSTGRES ], ): usockenv = { self._dbenvkeys[DEK.HOST]: '', # usock self._dbenvkeys[DEK.PORT]: '', self._dbenvkeys[DEK.SECURED]: False, self._dbenvkeys[DEK.HOST_VALIDATION]: False, self._dbenvkeys[DEK.USER]: 'postgres', self._dbenvkeys[DEK.PASSWORD]: '', self._dbenvkeys[DEK.DATABASE]: 'template1', } self._waitForDatabase( environment=usockenv, ) existing = self._userExists( environment=usockenv, ) self._performDatabase( environment=usockenv, op=( 'alter' if existing else 'create' ), ) finally: # restore everything localtransaction.abort() self._restart()
def _misc(self): fd, self._image_path = tempfile.mkstemp( dir=self.environment[ohostedcons.CoreEnv.TEMPDIR], ) os.close(fd) with transaction.Transaction() as localtransaction: localtransaction.append( ImageTransaction( parent=self, tar=self.environment[ohostedcons.VMEnv.OVF], src=self._source_image, dst=self._image_path, ))
def createUser(self): if not self.supported(): raise RuntimeError( _('Unsupported distribution for ' 'postgresql proisioning')) self._initDbIfRequired() localtransaction = transaction.Transaction() try: localtransaction.prepare() self._setPgHbaLocalPeer(transaction=localtransaction, ) self.restartPG() with AlternateUser(user=self.environment[ oengcommcons.SystemEnv.USER_POSTGRES], ): usockenv = { self._dbenvkeys[DEK.HOST]: '', # usock self._dbenvkeys[DEK.PORT]: '', self._dbenvkeys[DEK.SECURED]: False, self._dbenvkeys[DEK.HOST_VALIDATION]: False, self._dbenvkeys[DEK.USER]: 'postgres', self._dbenvkeys[DEK.PASSWORD]: '', self._dbenvkeys[DEK.DATABASE]: 'template1', } self._waitForDatabase(environment=usockenv, ) perform_role_sql = (""" {op} role {user} with login encrypted password %(password)s """).format( op=('alter' if self._userExists( environment=usockenv) else 'create'), user=_ind_env(self, DEK.USER), ) database.Statement( dbenvkeys=self._dbenvkeys, environment=usockenv, ).execute( statement=perform_role_sql, args=dict(password=_ind_env(self, DEK.PASSWORD), ), ownConnection=True, transaction=False, ) finally: # restore everything localtransaction.abort() self.restartPG()
def _getSSH(self): pkihelper = pkissh.PKIHelper() authorized_keys_line = pkihelper.getSSHkey( fqdn=self.environment[ ohostedcons.NetworkEnv.OVIRT_HOSTED_ENGINE_FQDN ], ca_certs=self.environment[ ohostedcons.EngineEnv.TEMPORARY_CERT_FILE ], ) authorized_keys_file = os.path.join( os.path.expanduser('~root'), '.ssh', 'authorized_keys' ) content = pkihelper.mergeAuthKeysFile( authorized_keys_file, authorized_keys_line ) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=authorized_keys_file, content=content, mode=0o600, owner='root', enforcePermissions=True, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ) ) if self._selinux_enabled: path = os.path.join( os.path.expanduser('~root'), '.ssh' ) try: selinux.restorecon(path, recursive=True) except OSError as ex: self.logger.error( _( 'Failed to refresh SELINUX context for {path}: {ex}' ).format( path=path, ex=ex.message, ) )
def _update_templates(self, aia, templates_map, uninstall_files): localtransaction = transaction.Transaction() with localtransaction: for in_template, outputs in templates_map.items(): if aia is not None: for output_file in outputs: localtransaction.append( filetransaction.FileTransaction( name=output_file, content=outil.processTemplate( in_template, { '@AIA@': aia, }), modifiedList=uninstall_files, ), )
def _updatePGConf(self): self.logger.info(_('Updating PostgreSQL configuration')) with transaction.Transaction() as localtransaction: self._provisioning._updatePostgresConf( transaction=localtransaction, ) self._provisioning.restartPG() dbutils = database.OvirtUtils( plugin=self, dbenvkeys=oenginecons.Const.ENGINE_DB_ENV_KEYS, environment=self.environment) invalid_config_items = dbutils.validateDbConf('Engine', self.environment) if invalid_config_items: raise RuntimeError( database.getInvalidConfigItemsMessage(invalid_config_items))
def _write_new_config(self, file_name, content): timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') new_file_name = "{}.new.{}".format(file_name, timestamp) # If we are writing a new file, write it immediately. # Note that this will not be rolled back by engine-setup # if there is some failure. local_transaction = transaction.Transaction() with local_transaction: local_transaction.append( filetransaction.FileTransaction( name=new_file_name, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], )) self._notifications.append((file_name, new_file_name))
def _misc_conffiles(self): self.environment[ osetupcons.CoreEnv.REGISTER_UNINSTALL_GROUPS ].createGroup( group='ca_pki', description='PKI keys', optional=True, ).addFiles( group='ca_pki', fileList=self.uninstall_files, ) localtransaction = transaction.Transaction() with localtransaction: for config in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE[ :-len('.in')], oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_CONF ): with open(config, 'r') as f: content = [] for line in f: line = line.rstrip('\n') if line.startswith('authorityInfoAccess'): line = ( 'authorityInfoAccess = ' 'caIssuers;URI:http://%s:%s%s' ) % ( self.environment[ osetupcons.RenameEnv.FQDN ], self.environment[ oengcommcons.ConfigEnv.PUBLIC_HTTP_PORT ], oenginecons.Const.ENGINE_PKI_CA_URI, ) content.append(line) localtransaction.append( filetransaction.FileTransaction( name=config, content=content, modifiedList=self.uninstall_files, ), )
def _closeup(self): self.environment[ ohostedcons.VMEnv.SUBST]['@BOOT_DISK@'] = ',bootOrder:1' self.environment[ohostedcons.VMEnv.SUBST]['@BOOT_PXE@'] = '' self.environment[ohostedcons.VMEnv.SUBST]['@BOOT_CDROM@'] = '' # Eject the cd-rom if present self.environment[ohostedcons.VMEnv.SUBST]['@CDROM@'] = '' content = ohostedutil.processTemplate( template=ohostedcons.FileLocations.ENGINE_VM_TEMPLATE, subst=self.environment[ohostedcons.VMEnv.SUBST], ) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.ENGINE_VM_CONF, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], ), )
def _expandPKCS12(self, pkcs12, name, owner, uninstall_files): rc, key, stderr = self.execute( args=( self.command.get('openssl'), 'pkcs12', '-in', pkcs12, '-passin', 'pass:%s' % self.environment[ oenginecons.PKIEnv.STORE_PASS ], '-nodes', '-nocerts', ), logStreams=False, ) localtransaction = transaction.Transaction() with localtransaction: localtransaction.append( filetransaction.FileTransaction( name=os.path.join( oenginecons.FileLocations.OVIRT_ENGINE_PKICERTSDIR, '%s.cer' % name, ), content=self._extractPKCS12CertificateString(pkcs12), mode=0o644, modifiedList=uninstall_files, ) ) localtransaction.append( filetransaction.FileTransaction( name=os.path.join( oenginecons.FileLocations.OVIRT_ENGINE_PKIKEYSDIR, '%s.key.nopass' % name, ), content=key, mode=0o600, owner=owner, modifiedList=uninstall_files, ) )
def _misc(self): self.logger.info(_('Configuring libvirt')) old_content = [] if os.path.exists(ohostedcons.FileLocations.LIBVIRT_QEMU_CONF): with open(ohostedcons.FileLocations.LIBVIRT_QEMU_CONF, 'r') as f: old_content = f.read().splitlines() new_content = [] new_conf = 'lock_manager="sanlock"' found = False for line in old_content: match = self.RE_LOCK_MANAGER.match(line) if match: found = True self.logger.debug( 'Changing lock_manager from {old} to sanlock'.format( old=match.group(1))) line = new_conf new_content.append(line) if not found: new_content.append(new_conf) with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.LIBVIRT_QEMU_CONF, content=new_content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], ), ) if not self.services.supportsDependency: if self.services.exists('cgconfig'): self.services.state('cgconfig', True) self.services.startup('cgconfig', True) if self.services.exists('messagebus'): self.services.state('messagebus', True) self.services.startup('messagebus', True) if self.services.exists('libvirtd'): self.services.state('libvirtd', True) self.services.startup('libvirtd', True) self._restartLibvirt()
def _closeup(self): self.environment[ ohostedcons.VMEnv.SUBST]['@BOOT_DISK@'] = ',bootOrder:1' self.environment[ohostedcons.VMEnv.SUBST]['@BOOT_PXE@'] = '' self.environment[ohostedcons.VMEnv.SUBST]['@BOOT_CDROM@'] = '' # Eject the cd-rom if present self.environment[ohostedcons.VMEnv.SUBST]['@CDROM@'] = '' content = ohostedutil.processTemplate( template=ohostedcons.FileLocations.ENGINE_VM_TEMPLATE, subst=self.environment[ohostedcons.VMEnv.SUBST], ) self.environment[ohostedcons.StorageEnv.VM_CONF_CONTENT] = content with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.ENGINE_VM_CONF, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], mode=0o600, owner=ohostedcons.Defaults.DEFAULT_SYSTEM_USER_VDSM, group=ohostedcons.Defaults.DEFAULT_SYSTEM_GROUP_KVM, enforcePermissions=True, ), )
def _misc(self): self._enabled = True # TODO # this implementaiton is not transactional # too many issues with legacy ca implementation # need to work this out to allow transactional # for now just delete files if we fail uninstall_files = [] self._setupUninstall(uninstall_files) self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( self.CATransaction( parent=self, uninstall_files=uninstall_files, )) # LEGACY NOTE # This is needed for avoiding error in create_ca when supporting # max cn length of 64. # please DON'T increase this size, any value over 55 will fail the # setup. the truncated host-fqdn is concatenated with a random string # to create a unique CN value. MAX_HOST_FQDN_LEN = 55 self.logger.info(_('Creating CA')) localtransaction = transaction.Transaction() with localtransaction: for name in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_TEMPLATE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE, ): localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.in')], content=outil.processTemplate( name, { '@AIA@': 'http://%s:%s%s' % ( self.environment[ osetupcons.ConfigEnv.FQDN], self.environment[oengcommcons.ConfigEnv. PUBLIC_HTTP_PORT], oenginecons.Const.ENGINE_PKI_CA_URI, ) }), modifiedList=uninstall_files, ), ) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CREATE, '--subject=/C=%s/O=%s/CN=%s.%s' % ( self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.COUNTRY], ), self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.ORG], ), self._subjectComponentEscape( self.environment[osetupcons.ConfigEnv.FQDN] [:MAX_HOST_FQDN_LEN], ), random.randint(10000, 99999), ), '--keystore-password=%s' % (self.environment[oenginecons.PKIEnv.STORE_PASS], ), ), envAppend={ 'JAVA_HOME': self.environment[oengcommcons.ConfigEnv.JAVA_HOME], }, ) uninstall_files.extend(( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_KEY, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_TRUST_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CERT_CONF, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_CONF, )) if not os.path.exists( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT): os.symlink( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT, oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT) uninstall_files.append( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT) self._enrollCertificates(False, uninstall_files)
def _miscUpgrade(self): # # In <3.6 setup did not store the organization and # country in post install file. Load it from CA certificate. # if self.environment[oenginecons.PKIEnv.ORG] is None: ca = self._x509_load_cert( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT) self.environment[ oenginecons.PKIEnv.ORG] = ca.get_subject().get_entries_by_nid( X509.X509_Name.nid['O'])[0].get_data().as_text() self.environment[oenginecons.PKIEnv.COUNTRY] = ca.get_subject( ).get_entries_by_nid( X509.X509_Name.nid['C'])[0].get_data().as_text() self.logger.info(_('Upgrading CA')) # # LEGACY NOTE # Since 3.0 and maybe before the method of # allowing user to override AIA was to explict # edit files. Until we rewrite the entire PKI # we must preserve this approach. # The template may change over time, so regenerate. # aia = None template = oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE[:-len( '.in')] if os.path.exists(template): with open(template) as f: PREFIX = 'caIssuers;URI:' for l in f.read().splitlines(): if l.startswith('authorityInfoAccess'): aia = l[l.find(PREFIX) + len(PREFIX):] break uninstall_files = [] self._setupUninstall(uninstall_files) if aia is not None: localtransaction = transaction.Transaction() with localtransaction: for name in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_TEMPLATE, oenginecons.FileLocations. OVIRT_ENGINE_PKI_CERT_TEMPLATE, ): localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.in')], content=outil.processTemplate( name, { '@AIA@': aia, }), modifiedList=uninstall_files, ), ) localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.template.in')] + '.conf', content=outil.processTemplate( name, { '@AIA@': aia, }), modifiedList=uninstall_files, ), ) if self.environment[oenginecons.PKIEnv.RENEW]: if self._expired( self._x509_load_cert(oenginecons.FileLocations. OVIRT_ENGINE_PKI_ENGINE_CA_CERT)): self._ca_was_renewed = True self.logger.info(_('Renewing CA')) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CREATE, '--renew', '--keystore-password=%s' % (self.environment[oenginecons.PKIEnv.STORE_PASS], ), ), envAppend={ 'JAVA_HOME': self.environment[oengcommcons.ConfigEnv.JAVA_HOME], }, ) self._enrollCertificates(True, uninstall_files) # Also enroll missing parts on upgrade if os.path.exists( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT): self._enrollCertificates(False, uninstall_files)
def _misc(self): self.logger.info(_('Configuring VM')) subst = { '@SP_UUID@': ohostedcons.Const.BLANK_UUID, '@SD_UUID@': self.environment[ohostedcons.StorageEnv.SD_UUID], '@VOL_UUID@': self.environment[ohostedcons.StorageEnv.VOL_UUID], '@IMG_UUID@': self.environment[ohostedcons.StorageEnv.IMG_UUID], '@VM_UUID@': self.environment[ohostedcons.VMEnv.VM_UUID], '@MEM_SIZE@': self.environment[ohostedcons.VMEnv.MEM_SIZE_MB], '@MAC_ADDR@': self.environment[ohostedcons.VMEnv.MAC_ADDR], '@NAME@': ohostedcons.Const.HOSTED_ENGINE_VM_NAME, '@CONSOLE_TYPE@': self.environment[ohostedcons.VMEnv.CONSOLE_TYPE], '@VCPUS@': self.environment[ohostedcons.VMEnv.VCPUS], '@MAXVCPUS@': self.environment[ohostedcons.VMEnv.MAXVCPUS], '@CPU_TYPE@': self.environment[ohostedcons.VDSMEnv.VDSM_CPU].replace( 'model_', ''), '@EMULATED_MACHINE@': self.environment[ohostedcons.VMEnv.EMULATED_MACHINE], '@CDROM_UUID@': self.environment[ohostedcons.VMEnv.CDROM_UUID], '@NIC_UUID@': self.environment[ohostedcons.VMEnv.NIC_UUID], '@CONSOLE_UUID@': self.environment[ohostedcons.VMEnv.CONSOLE_UUID], '@BRIDGE@': self.environment[ohostedcons.NetworkEnv.BRIDGE_NAME], } if self.environment[ohostedcons.VMEnv.CONSOLE_TYPE] == 'vnc': subst['@VIDEO_DEVICE@'] = 'vga' subst['@GRAPHICS_DEVICE@'] = 'vnc' else: subst['@VIDEO_DEVICE@'] = 'qxl' subst['@GRAPHICS_DEVICE@'] = 'spice' if self.environment[ohostedcons.VMEnv.CDROM]: subst['@CDROM@'] = self.environment[ohostedcons.VMEnv.CDROM] else: subst['@CDROM@'] = '' content = ohostedutil.processTemplate( template=ohostedcons.FileLocations.ENGINE_VM_TEMPLATE, subst=subst, ) self.environment[ohostedcons.VMEnv.SUBST] = subst with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.ENGINE_VM_CONF, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], mode=0o600, owner=ohostedcons.Defaults.DEFAULT_SYSTEM_USER_VDSM, group=ohostedcons.Defaults.DEFAULT_SYSTEM_GROUP_KVM, downer=ohostedcons.Defaults.DEFAULT_SYSTEM_USER_VDSM, dgroup=ohostedcons.Defaults.DEFAULT_SYSTEM_GROUP_KVM, enforcePermissions=True, ), )
def _misc(self): self.logger.info(_('Configuring VM')) subst = { '@SP_UUID@': ohostedcons.Const.BLANK_UUID, '@SD_UUID@': self.environment[ ohostedcons.StorageEnv.SD_UUID ], '@VOL_UUID@': self.environment[ ohostedcons.StorageEnv.VOL_UUID ], '@IMG_UUID@': self.environment[ ohostedcons.StorageEnv.IMG_UUID ], '@VM_UUID@': self.environment[ ohostedcons.VMEnv.VM_UUID ], '@MEM_SIZE@': self.environment[ ohostedcons.VMEnv.MEM_SIZE_MB ], '@MAC_ADDR@': self.environment[ ohostedcons.VMEnv.MAC_ADDR ], '@NAME@': ohostedcons.Const.HOSTED_ENGINE_VM_NAME, '@CONSOLE_TYPE@': self.environment[ ohostedcons.VMEnv.CONSOLE_TYPE ], '@VCPUS@': self.environment[ ohostedcons.VMEnv.VCPUS ], '@CPU_TYPE@': self.environment[ ohostedcons.VDSMEnv.VDSM_CPU ].replace('model_', ''), '@EMULATED_MACHINE@': self.environment[ ohostedcons.VMEnv.EMULATED_MACHINE ], '@CDROM_UUID@': self.environment[ ohostedcons.VMEnv.CDROM_UUID ], '@NIC_UUID@': self.environment[ ohostedcons.VMEnv.NIC_UUID ], '@CONSOLE_UUID@': self.environment[ ohostedcons.VMEnv.CONSOLE_UUID ], '@BRIDGE@': self.environment[ ohostedcons.NetworkEnv.BRIDGE_NAME ], } if self.environment[ ohostedcons.VMEnv.BOOT ] in self.BOOT_DEVICE.keys(): for key in self.BOOT_DEVICE.keys(): if key != self.environment[ohostedcons.VMEnv.BOOT]: subst[self.BOOT_DEVICE[key]] = '' else: subst[self.BOOT_DEVICE[key]] = ',bootOrder:1' if self.environment[ ohostedcons.VMEnv.CDROM ]: subst['@CDROM@'] = self.environment[ ohostedcons.VMEnv.CDROM ] else: subst['@CDROM@'] = '' content = ohostedutil.processTemplate( template=ohostedcons.FileLocations.ENGINE_VM_TEMPLATE, subst=subst, ) self.environment[ohostedcons.VMEnv.SUBST] = subst with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=ohostedcons.FileLocations.ENGINE_VM_CONF, content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ), )
def _misc_config(self): # If running on the engine machine, use key/cert created for httpd. # In the past, we used our own pki. # Only replace the config file if user didn't touch it since last # run of engine-setup. Otherwise, write a new file and notify the user. conffile = oipcons.FileLocations.OVIRT_IMAGEIO_PROXY_CONFIG newcontent = self._get_configuration() oldcontent = '' if os.path.exists(conffile): with open(conffile) as f: oldcontent = f.read() if self._conffile_was_written_by_previous_setup(conffile): if not self._conffile_was_changed_since_previous_setup(conffile): self.logger.info( _( 'Updating {f} to use apache key and certificate' ).format( f=conffile, ) ) elif oldcontent == newcontent: # We wrote the file in the past, the user changed it, but # changed it to have the same content we already want to write. # So output nothing to the user, but still re-write the file, # so that we have the new hash in uninstall info. self.logger.debug( 'Rewriting %s in order to update uninstall info', conffile, ) else: # Write a new file, do not touch existing one that user # changed, and notify the user. self._new_filename = '{old}.new'.format( old=conffile, ) if os.path.exists(self._new_filename): self._new_filename = '{newf}.{timestamp}'.format( newf=self._new_filename, timestamp=datetime.datetime.now().strftime( '%Y%m%d%H%M%S' ), ) self.logger.info( _( 'Not rewriting {f} because it was changed manually. ' 'You might want to compare it with {fnew} and edit as ' 'needed.' ).format( f=conffile, fnew=self._new_filename, ) ) if self._new_filename: # If we are writing a new file, write it immediately. # Note that this will not be rolled back by engine-setup # if there is some failure. localtransaction = transaction.Transaction() with localtransaction: localtransaction.append( filetransaction.FileTransaction( name=self._new_filename, content=newcontent, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ) ) else: # If updating the existing file (or writing it new), do this # in the main transaction. So will be rolled back if there is # a problem. self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( filetransaction.FileTransaction( name=conffile, content=newcontent, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES ], ) )
def _misc(self): # TODO # this implementaiton is not transactional # too many issues with legacy ca implementation # need to work this out to allow transactional # for now just delete files if we fail uninstall_files = [] self.environment[otopicons.CoreEnv.MAIN_TRANSACTION].append( self.CATransaction( parent=self, uninstall_files=uninstall_files, ) ) # LEGACY NOTE # This is needed for avoiding error in create_ca when supporting # max cn length of 64. # please DON'T increase this size, any value over 55 will fail the # setup. the truncated host-fqdn is concatenated with a random string # to create a unique CN value. self.environment[ osetupcons.CoreEnv.REGISTER_UNINSTALL_GROUPS ].createGroup( group='ca_pki', description='PKI keys', optional=True, ).addFiles( group='ca_pki', fileList=uninstall_files, ) MAX_HOST_FQDN_LEN = 55 self.logger.info(_('Creating CA')) localtransaction = transaction.Transaction() with localtransaction: for name in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_TEMPLATE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE, ): localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.in')], content=outil.processTemplate( name, { '@AIA@': 'http://%s:%s%s' % ( self.environment[ osetupcons.ConfigEnv.FQDN ], self.environment[ oengcommcons.ConfigEnv.PUBLIC_HTTP_PORT ], oenginecons.Const.ENGINE_PKI_CA_URI, ) } ), modifiedList=uninstall_files, ), ) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CREATE, '--subject=/C=%s/O=%s/CN=%s.%s' % ( self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.COUNTRY], ), self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.ORG], ), self._subjectComponentEscape( self.environment[ osetupcons.ConfigEnv.FQDN ][:MAX_HOST_FQDN_LEN], ), random.randint(10000, 99999), ), '--keystore-password=%s' % ( self.environment[oenginecons.PKIEnv.STORE_PASS], ), ), envAppend={ 'JAVA_HOME': self.environment[ oengcommcons.ConfigEnv.JAVA_HOME ], }, ) for name in ( 'engine', 'apache', 'jboss', 'websocket-proxy', 'reports' ): self.execute( ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_ENROLL, '--name=%s' % name, '--password=%s' % ( self.environment[oenginecons.PKIEnv.STORE_PASS], ), '--subject=/C=%s/O=%s/CN=%s' % ( self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.COUNTRY], ), self._subjectComponentEscape( self.environment[oenginecons.PKIEnv.ORG], ), self._subjectComponentEscape( self.environment[osetupcons.ConfigEnv.FQDN], ), ), ), ) uninstall_files.extend( ( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_APACHE_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_KEY, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_TRUST_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_CERT, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CERT_CONF, oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_CONF, ( oenginecons.FileLocations. OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_CERT ), ( oenginecons.FileLocations. OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_STORE ), ) ) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, '--name=websocket-proxy', '--passin=%s' % ( self.environment[oenginecons.PKIEnv.STORE_PASS], ), '--key=%s' % ( oenginecons.FileLocations. OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_KEY, ), ), logStreams=False, ) uninstall_files.append( oenginecons.FileLocations. OVIRT_ENGINE_PKI_LOCAL_WEBSOCKET_PROXY_KEY ) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, '--name=reports', '--passin=%s' % ( self.environment[oenginecons.PKIEnv.STORE_PASS], ), '--key=%s' % ( oenginecons.FileLocations. OVIRT_ENGINE_PKI_REPORTS_KEY, ), ), logStreams=False, ) uninstall_files.append( oenginecons.FileLocations. OVIRT_ENGINE_PKI_REPORTS_KEY ) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_PKCS12_EXTRACT, '--name=apache', '--passin=%s' % ( self.environment[oenginecons.PKIEnv.STORE_PASS], ), '--key=%s' % ( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_KEY, ), ), logStreams=False, ) uninstall_files.append( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_KEY ) if not os.path.exists( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT ): os.symlink( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT, oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT ) uninstall_files.append( oengcommcons.FileLocations.OVIRT_ENGINE_PKI_APACHE_CA_CERT ) for f in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_STORE, oenginecons.FileLocations.OVIRT_ENGINE_PKI_JBOSS_STORE, ): os.chown( f, osetuputil.getUid( self.environment[osetupcons.SystemEnv.USER_ENGINE] ), -1, )
def _misc(self): if not os.path.exists(self.environment[ osetupcons.ProvisioningEnv.POSTGRES_PG_VERSION]): self._initDB() self.logger.info(_('Creating PostgreSQL database')) localtransaction = transaction.Transaction() try: localtransaction.prepare() self._setPgHbaLocalPeer( transaction=localtransaction, filename=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_PG_HBA], ) # restart to take effect for state in (False, True): self.services.state( name=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_SERVICE], state=state, ) with self._alternateUser(user=self.environment[ osetupcons.SystemEnv.USER_POSTGRES], ): usockenv = { osetupcons.DBEnv.HOST: '', # usock osetupcons.DBEnv.PORT: '', osetupcons.DBEnv.SECURED: False, osetupcons.DBEnv.SECURED_HOST_VALIDATION: False, osetupcons.DBEnv.USER: '******', osetupcons.DBEnv.PASSWORD: '', osetupcons.DBEnv.DATABASE: 'template1', } self._waitDatabase(environment=usockenv, ) existing = self._setDatabaseResources(environment=usockenv, ) self._performDatabase( environment=usockenv, op=('alter' if existing else 'create'), user=self.environment[osetupcons.DBEnv.USER], password=self.environment[osetupcons.DBEnv.PASSWORD], databaseName=self.environment[osetupcons.DBEnv.DATABASE], ) finally: # restore everything localtransaction.abort() self.logger.info(_('Configurating PostgreSQL')) localtransaction = transaction.Transaction() with localtransaction: self._addPgHbaDatabaseAccess( transaction=localtransaction, filename=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_PG_HBA], ) self._updateMaxConnections( transaction=localtransaction, filename=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_CONF], maxconn=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_MAX_CONN], ) # restart to take effect for state in (False, True): self.services.state( name=self.environment[ osetupcons.ProvisioningEnv.POSTGRES_SERVICE], state=state, ) self.services.startup( name=self.environment[osetupcons.ProvisioningEnv.POSTGRES_SERVICE], state=True, ) self._waitDatabase()
def _misc(self): self.logger.info(_('Updating hosted-engine configuration')) subst = { '@FQDN@': self.environment[ohostedcons.NetworkEnv.OVIRT_HOSTED_ENGINE_FQDN], '@VM_DISK_ID@': self.environment[ohostedcons.StorageEnv.IMG_UUID], '@VM_DISK_VOL_ID@': self.environment[ohostedcons.StorageEnv.VOL_UUID], '@SHARED_STORAGE@': self.environment[ohostedcons.StorageEnv.STORAGE_DOMAIN_CONNECTION], '@CONSOLE_TYPE@': self.environment[ohostedcons.VMEnv.CONSOLE_TYPE], '@VM_UUID@': self.environment[ohostedcons.VMEnv.VM_UUID], '@CONF_FILE@': ohostedcons.FileLocations.ENGINE_VM_CONF, '@HOST_ID@': self.environment[ohostedcons.StorageEnv.HOST_ID], '@DOMAIN_TYPE@': self.environment[ohostedcons.StorageEnv.DOMAIN_TYPE], '@MNT_OPTIONS@': self.environment[ohostedcons.StorageEnv.MNT_OPTIONS] or '', '@SP_UUID@': self.environment[ohostedcons.StorageEnv.SP_UUID], '@SD_UUID@': self.environment[ohostedcons.StorageEnv.SD_UUID], '@CONNECTION_UUID@': self.environment[ohostedcons.StorageEnv.CONNECTION_UUID], '@CA_CERT@': ohostedcons.FileLocations.LIBVIRT_SPICE_CA_CERT, '@CA_SUBJECT@': self.environment[ohostedcons.VDSMEnv.SPICE_SUBJECT], '@VDSM_USE_SSL@': str(self.environment[ohostedcons.VDSMEnv.USE_SSL]).lower(), '@GATEWAY@': self.environment[ohostedcons.NetworkEnv.GATEWAY], '@BRIDGE@': self.environment[ohostedcons.NetworkEnv.BRIDGE_NAME], '@METADATA_VOLUME_UUID@': self.environment[ohostedcons.StorageEnv.METADATA_VOLUME_UUID], '@METADATA_IMAGE_UUID@': self.environment[ohostedcons.StorageEnv.METADATA_IMAGE_UUID], '@LOCKSPACE_VOLUME_UUID@': self.environment[ohostedcons.StorageEnv.LOCKSPACE_VOLUME_UUID], '@LOCKSPACE_IMAGE_UUID@': self.environment[ohostedcons.StorageEnv.LOCKSPACE_IMAGE_UUID], '@CONF_VOLUME_UUID@': self.environment[ohostedcons.StorageEnv.CONF_VOL_UUID], '@CONF_IMAGE_UUID@': self.environment[ohostedcons.StorageEnv.CONF_IMG_UUID], '@IQN@': '', '@PORTAL@': '', '@USER@': '', '@PASSWORD@': '', '@PORT@': '', } if self.environment[ohostedcons.StorageEnv.DOMAIN_TYPE] in ( ohostedcons.DomainTypes.ISCSI, ): # Defaults are ok for NFS and GlusterFS, need to change only # for iSCSI subst['@SHARED_STORAGE@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_IP_ADDR] subst['@IQN@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_TARGET] subst['@PORTAL@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_PORTAL] subst['@USER@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_USER] subst['@PASSWORD@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_PASSWORD] subst['@PORT@'] = self.environment[ ohostedcons.StorageEnv.ISCSI_PORT] content = ohostedutil.processTemplate( template=ohostedcons.FileLocations.OVIRT_HOSTED_ENGINE_TEMPLATE, subst=subst) self.environment[ohostedcons.StorageEnv.HECONF_CONTENT] = content with transaction.Transaction() as localtransaction: localtransaction.append( filetransaction.FileTransaction( name=(ohostedcons.FileLocations. OVIRT_HOSTED_ENGINE_SETUP_CONF), content=content, modifiedList=self.environment[ otopicons.CoreEnv.MODIFIED_FILES], ), )
def _miscUpgrade(self): self.logger.info(_('Upgrading CA')) # # LEGACY NOTE # Since 3.0 and maybe before the method of # allowing user to override AIA was to explict # edit files. Until we rewrite the entire PKI # we must preserve this approach. # The template may change over time, so regenerate. # aia = None template = oenginecons.FileLocations.OVIRT_ENGINE_PKI_CERT_TEMPLATE[:-len( '.in')] if os.path.exists(template): with open(template) as f: PREFIX = 'caIssuers;URI:' for l in f.readlines(): if l.startswith('authorityInfoAccess'): aia = l[l.find(PREFIX) + len(PREFIX):] break uninstall_files = [] self._setupUninstall(uninstall_files) if aia is not None: localtransaction = transaction.Transaction() with localtransaction: for name in ( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_TEMPLATE, oenginecons.FileLocations. OVIRT_ENGINE_PKI_CERT_TEMPLATE, ): localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.in')], content=outil.processTemplate( name, { '@AIA@': aia, }), modifiedList=uninstall_files, ), ) localtransaction.append( filetransaction.FileTransaction( name=name[:-len('.template.in')] + '.conf', content=outil.processTemplate( name, { '@AIA@': aia, }), modifiedList=uninstall_files, ), ) # # LEGACY NOTE # Since 3.0 and maybe before the CA certificate's # notBefore attribute was set using timezone offset # instead of Z # in this case we need to reissue CA certificate. # x509 = X509.load_cert( oenginecons.FileLocations.OVIRT_ENGINE_PKI_ENGINE_CA_CERT) if x509.get_not_before().get_datetime().tzname() is None: self._ca_was_renewed = True self.logger.info(_('Renewing CA')) self.execute( args=( oenginecons.FileLocations.OVIRT_ENGINE_PKI_CA_CREATE, '--renew', '--keystore-password=%s' % (self.environment[oenginecons.PKIEnv.STORE_PASS], ), ), envAppend={ 'JAVA_HOME': self.environment[oengcommcons.ConfigEnv.JAVA_HOME], }, )