1<template>
2  <b-container fluid="xl">
3    <page-title />
4    <b-row class="mb-4">
5      <b-col md="12">
6        <page-section
7          :section-title="$t('pageVirtualMedia.virtualMediaSubTitleFirst')"
8        >
9          <b-row>
10            <b-col v-for="(dev, $index) in proxyDevices" :key="$index" md="6">
11              <b-form-group :label="dev.id" label-class="bold">
12                <form-file
13                  v-if="!dev.isActive"
14                  :id="concatId(dev.id)"
15                  v-model="dev.file"
16                >
17                  <template #invalid>
18                    <b-form-invalid-feedback role="alert">
19                      {{ $t('global.form.required') }}
20                    </b-form-invalid-feedback>
21                  </template>
22                </form-file>
23              </b-form-group>
24              <b-button
25                v-if="!dev.isActive"
26                variant="primary"
27                :disabled="!dev.file"
28                @click="startVM(dev)"
29              >
30                {{ $t('pageVirtualMedia.start') }}
31              </b-button>
32              <b-button
33                v-if="dev.isActive"
34                variant="primary"
35                :disabled="!dev.file"
36                @click="stopVM(dev)"
37              >
38                {{ $t('pageVirtualMedia.stop') }}
39              </b-button>
40            </b-col>
41          </b-row>
42        </page-section>
43      </b-col>
44    </b-row>
45    <b-row v-if="loadImageFromExternalServer" class="mb-4">
46      <b-col md="12">
47        <page-section
48          :section-title="$t('pageVirtualMedia.virtualMediaSubTitleSecond')"
49        >
50          <b-row>
51            <b-col
52              v-for="(device, $index) in legacyDevices"
53              :key="$index"
54              md="6"
55            >
56              <b-form-group
57                :label="device.id"
58                :label-for="device.id"
59                label-class="bold"
60              >
61                <b-button
62                  variant="primary"
63                  :disabled="device.isActive"
64                  @click="configureConnection(device)"
65                >
66                  {{ $t('pageVirtualMedia.configureConnection') }}
67                </b-button>
68
69                <b-button
70                  v-if="!device.isActive"
71                  variant="primary"
72                  class="float-right"
73                  :disabled="!device.serverUri"
74                  @click="startLegacy(device)"
75                >
76                  {{ $t('pageVirtualMedia.start') }}
77                </b-button>
78                <b-button
79                  v-if="device.isActive"
80                  variant="primary"
81                  class="float-right"
82                  @click="stopLegacy(device)"
83                >
84                  {{ $t('pageVirtualMedia.stop') }}
85                </b-button>
86              </b-form-group>
87            </b-col>
88          </b-row>
89        </page-section>
90      </b-col>
91    </b-row>
92    <modal-configure-connection
93      :connection="modalConfigureConnection"
94      @ok="saveConnection"
95    />
96  </b-container>
97</template>
98
99<script>
100import PageTitle from '@/components/Global/PageTitle';
101import PageSection from '@/components/Global/PageSection';
102import BVToastMixin from '@/components/Mixins/BVToastMixin';
103import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
104import ModalConfigureConnection from './ModalConfigureConnection';
105import NbdServer from '@/utilities/NBDServer';
106import FormFile from '@/components/Global/FormFile';
107
108export default {
109  name: 'VirtualMedia',
110  components: { PageTitle, PageSection, ModalConfigureConnection, FormFile },
111  mixins: [BVToastMixin, LoadingBarMixin],
112  data() {
113    return {
114      modalConfigureConnection: null,
115      loadImageFromExternalServer:
116        process.env.VUE_APP_VIRTUAL_MEDIA_LIST_ENABLED === 'true'
117          ? true
118          : false,
119    };
120  },
121  computed: {
122    proxyDevices() {
123      return this.$store.getters['virtualMedia/proxyDevices'];
124    },
125    legacyDevices() {
126      return this.$store.getters['virtualMedia/legacyDevices'];
127    },
128  },
129  created() {
130    this.$store.dispatch('global/getSystemInfo');
131    if (this.proxyDevices.length > 0 || this.legacyDevices.length > 0) return;
132    this.startLoader();
133    this.$store
134      .dispatch('virtualMedia/getData')
135      .finally(() => this.endLoader());
136  },
137  methods: {
138    startVM(device) {
139      const token = this.$store.getters['authentication/token'];
140      device.nbd = new NbdServer(
141        `wss://${window.location.host}${device.websocket}`,
142        device.file,
143        device.id,
144        token
145      );
146      device.nbd.socketStarted = () =>
147        this.successToast(this.$t('pageVirtualMedia.toast.serverRunning'));
148      device.nbd.errorReadingFile = () =>
149        this.errorToast(this.$t('pageVirtualMedia.toast.errorReadingFile'));
150      device.nbd.socketClosed = (code) => {
151        if (code === 1000)
152          this.successToast(
153            this.$t('pageVirtualMedia.toast.serverClosedSuccessfully')
154          );
155        else
156          this.errorToast(
157            this.$t('pageVirtualMedia.toast.serverClosedWithErrors')
158          );
159        device.file = null;
160        device.isActive = false;
161      };
162
163      device.nbd.start();
164      device.isActive = true;
165    },
166    stopVM(device) {
167      device.nbd.stop();
168    },
169    startLegacy(connectionData) {
170      var data = {};
171      data.Image = connectionData.serverUri;
172      data.UserName = connectionData.username;
173      data.Password = connectionData.password;
174      data.WriteProtected = !connectionData.isRW;
175      this.startLoader();
176      this.$store
177        .dispatch('virtualMedia/mountImage', {
178          id: connectionData.id,
179          data: data,
180        })
181        .then(() => {
182          this.successToast(
183            this.$t('pageVirtualMedia.toast.serverConnectionEstablished')
184          );
185          connectionData.isActive = true;
186        })
187        .catch(() => {
188          this.errorToast(this.$t('pageVirtualMedia.toast.errorMounting'));
189          this.isActive = false;
190        })
191        .finally(() => this.endLoader());
192    },
193    stopLegacy(connectionData) {
194      this.$store
195        .dispatch('virtualMedia/unmountImage', connectionData.id)
196        .then(() => {
197          this.successToast(
198            this.$t('pageVirtualMedia.toast.serverClosedSuccessfully')
199          );
200          connectionData.isActive = false;
201        })
202        .catch(() =>
203          this.errorToast(this.$t('pageVirtualMedia.toast.errorUnmounting'))
204        )
205        .finally(() => this.endLoader());
206    },
207    saveConnection(connectionData) {
208      this.modalConfigureConnection.serverUri = connectionData.serverUri;
209      this.modalConfigureConnection.username = connectionData.username;
210      this.modalConfigureConnection.password = connectionData.password;
211      this.modalConfigureConnection.isRW = connectionData.isRW;
212    },
213    configureConnection(connectionData) {
214      this.modalConfigureConnection = connectionData;
215      this.$bvModal.show('configure-connection');
216    },
217    concatId(val) {
218      return val.split(' ').join('_').toLowerCase();
219    },
220  },
221};
222</script>
223