Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core/app/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class Hosts(SQLModel, table=True):
hostname: str
ipaddress: str
username: Optional[str] = None
ssh: Optional[bool] = 0
ssh: Optional[int] = 0
pool_id: Optional[UUID] = Field(default=None, foreign_key="pools.id")
tags: Optional[str] = None
state: Optional[bool] = 0
Expand All @@ -77,7 +77,7 @@ def to_json(self):
"hostname": self.hostname,
"ipaddress": self.ipaddress,
"username": self.username,
"ssh": bool(self.ssh),
"ssh": int(self.ssh),
"pool_id": str(self.pool_id),
"tags": self.tags,
"state": bool(self.state)
Expand Down
2 changes: 2 additions & 0 deletions src/core/app/kvm/kvm_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# specific language governing permissions and limitations
# under the License.

# THIS FILE DOESN'T SEEM TO BE USED ANYWHERE IN THE PROJECT

from sqlmodel import Session, select
from fastapi.encoders import jsonable_encoder
from app.patch import ensure_uuid
Expand Down
9 changes: 4 additions & 5 deletions src/core/app/routes/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,19 @@ def retrieve_host():
engine = database.init_db_connection()

try:
records = []
with Session(engine) as session:
statement = select(Hosts)
results = session.exec(statement)
for host in results:
records.append(host)
for host in records:
hosts = session.exec(statement).all()

for host in hosts:
try:
shell.os_system(f"nc -z -w 1 {host.ipaddress} 22 > /dev/null")
host.state = 'Reachable'
except shell.ShellException:
# TODO Be more precise than before and check the exit code ?
host.state = 'Unreachable'
return jsonable_encoder(records)
return jsonable_encoder(hosts)
except Exception as e:
raise ValueError(e)

Expand Down
46 changes: 27 additions & 19 deletions src/core/app/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,31 +114,39 @@ def __init__(self, message):
def init_ssh_connection(host_id, ip_address, username):
shell.subprocess_run(f"ls -al {__get_local_ssh_directory().as_posix()}")

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:
client.connect(
hostname=ip_address,
username=username,
)
client.close()
except OSError:
raise ConnectionException(
"The hypervisor is unreachable.")
except paramiko.ssh_exception.AuthenticationException:
raise ConnectionException(
"Authentication to the hypervisor has failed.")

host.filter_host_by_id(host_id)
engine = database.init_db_connection()

with Session(engine) as session:
statement = select(Hosts).where(Hosts.id == ensure_uuid(host_id))
results = session.exec(statement)
data_host = results.one()
data_host.ssh = 1
data_host.username = username

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(
hostname=ip_address,
username=username,
)
client.close()
data_host.ssh = 1
except OSError:
data_host.ssh = 2
session.add(data_host)
session.commit()
session.refresh(data_host)
raise ConnectionException(
"The hypervisor is unreachable.")
except paramiko.ssh_exception.AuthenticationException:
data_host.ssh = 2
session.add(data_host)
session.commit()
session.refresh(data_host)
raise ConnectionException(
"Authentication to the hypervisor has failed.")

host.filter_host_by_id(host_id)

session.add(data_host)
session.commit()
session.refresh(data_host)
Expand Down
50 changes: 36 additions & 14 deletions src/ui/src/pages/admin/resources/hypervisors/HypervisorForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,48 @@
<va-card>
<va-card-title>
<FormHeader
:title="hypersivorId ? `Updating hypervisor ${stateHypervisor?.hostname ?? ''}` : 'Adding hypervisor'" />
:title="
hypersivorId
? `Updating hypervisor ${stateHypervisor?.hostname ?? ''}`
: 'Adding hypervisor'
"
/>
</va-card-title>
<va-card-content v-if="!hypervisorId || stateHypervisor">
<va-form ref="form">
<va-input label="Hostname" v-model="formHypervisor.hostname"
:rules="[(value) => value?.length > 0 || 'Field is required']" />
<va-input
label="Hostname"
v-model="formHypervisor.hostname"
:rules="[(value) => value?.length > 0 || 'Field is required']"
/>
<br />
<va-input label="IP Address or Domain Name" v-model="formHypervisor.ipAddress" :rules="[
(value) =>
value?.match(/^[0-9a-zA-Z.-]+$/) ||
'Field is required and must be a valid IP address or domain name.',
]" />
<va-input
label="IP Address or Domain Name"
v-model="formHypervisor.ipAddress"
:rules="[
(value) =>
value?.match(/^[0-9a-zA-Z.-]+$/) ||
'Field is required and must be a valid IP address or domain name.',
]"
/>
<br />
<va-select label="Select Pool" v-model="selectedPool" :options="poolOptions"
:rules="[(value) => value || 'Field is required']" />
<va-select
label="Select Pool"
v-model="selectedPool"
:options="poolOptions"
:rules="[(value) => value || 'Field is required']"
/>
<br />
<va-input label="Tag (optional)" v-model="formHypervisor.tags" />
</va-form>
<br />
<va-button class="mb-3" @click="$refs.form.validate() && (hypersivorId ? updateHypervisor() : addHypervisor())">
<va-button
class="mb-3"
@click="
$refs.form.validate() &&
(hypersivorId ? updateHypervisor() : addHypervisor())
"
>
{{ hypervisorId ? "Update" : "Add" }}
</va-button>
</va-card-content>
Expand All @@ -40,7 +62,7 @@ import FormHeader from "@/components/forms/FormHeader.vue";
export default {
components: {
...spinners,
FormHeader
FormHeader,
},
data() {
return {
Expand Down Expand Up @@ -129,8 +151,8 @@ export default {
color: "success",
});
})
.catch(error => {
console.error(error)
.catch((error) => {
console.error(error);
this.$vaToast.init({
title: "Unable to add hypervisor",
message: error?.response?.data?.detail ?? error,
Expand Down
Loading