001/* 002 * VM-Operator 003 * Copyright (C) 2025 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.vmoperator.runner.qemu; 020 021import java.io.IOException; 022import java.nio.file.Path; 023import org.jdrupes.vmoperator.runner.qemu.events.VserportChangeEvent; 024import org.jgrapes.core.Channel; 025import org.jgrapes.core.annotation.Handler; 026import org.jgrapes.util.events.ConfigurationUpdate; 027 028/** 029 * A component that handles the communication with an agent 030 * running in the VM. 031 * 032 * If the log level for this class is set to fine, the messages 033 * exchanged on the socket are logged. 034 */ 035public abstract class AgentConnector extends QemuConnector { 036 037 protected String channelId; 038 039 /** 040 * Instantiates a new agent connector. 041 * 042 * @param componentChannel the component channel 043 * @throws IOException Signals that an I/O exception has occurred. 044 */ 045 public AgentConnector(Channel componentChannel) throws IOException { 046 super(componentChannel); 047 } 048 049 /** 050 * As the initial configuration of this component depends on the 051 * configuration of the {@link Runner}, it doesn't have a handler 052 * for the {@link ConfigurationUpdate} event. The values are 053 * forwarded from the {@link Runner} instead. 054 * 055 * @param channelId the channel id 056 * @param socketPath the socket path 057 */ 058 /* default */ void configure(String channelId, Path socketPath) { 059 super.configure(socketPath); 060 this.channelId = channelId; 061 logger.fine(() -> getClass().getSimpleName() + " configured with" 062 + " channelId=" + channelId); 063 } 064 065 /** 066 * When the virtual serial port with the configured channel id has 067 * been opened call {@link #agentConnected()}. 068 * 069 * @param event the event 070 */ 071 @Handler 072 public void onVserportChanged(VserportChangeEvent event) { 073 if (event.id().equals(channelId) && event.isOpen()) { 074 agentConnected(); 075 } 076 } 077 078 /** 079 * Called when the agent in the VM opens the connection. The 080 * default implementation does nothing. 081 */ 082 @SuppressWarnings("PMD.EmptyMethodInAbstractClassShouldBeAbstract") 083 protected void agentConnected() { 084 // Default is to do nothing. 085 } 086}